xref: /petsc/src/dm/impls/plex/plex.c (revision d28dd30140d847c17e173aac31a1637535e3dc96)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h>
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
60c312b8eSJed Brown #include <petscsf.h>
7e228b242SToby Isaac #include <petscds.h>
8e412dcbdSMatthew G. Knepley #include <petscdraw.h>
9f19dbd58SToby Isaac #include <petscdmfield.h>
10012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
11552f7358SJed Brown 
12552f7358SJed Brown /* Logging support */
1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad;
14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate;
15552f7358SJed Brown 
16f39ec787SMatthew G. Knepley PetscBool  Plexcite       = PETSC_FALSE;
17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n"
18f39ec787SMatthew G. Knepley                             "title     = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n"
19f39ec787SMatthew G. Knepley                             "author    = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n"
20f39ec787SMatthew G. Knepley                             "journal   = {SIAM Journal on Scientific Computing},\n"
21f39ec787SMatthew G. Knepley                             "volume    = {38},\n"
22f39ec787SMatthew G. Knepley                             "number    = {5},\n"
23f39ec787SMatthew G. Knepley                             "pages     = {S143--S155},\n"
24f39ec787SMatthew G. Knepley                             "eprint    = {http://arxiv.org/abs/1506.07749},\n"
25f39ec787SMatthew G. Knepley                             "doi       = {10.1137/15M1026092},\n"
26f39ec787SMatthew G. Knepley                             "year      = {2016},\n"
27f39ec787SMatthew G. Knepley                             "petsc_uses={DMPlex},\n}\n";
28f39ec787SMatthew G. Knepley 
295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
30552f7358SJed Brown 
31e5337592SStefano Zampini /*@
329318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
339318fe57SMatthew G. Knepley 
349318fe57SMatthew G. Knepley   Input Parameter:
35a1cb98faSBarry Smith . dm - The `DMPLEX` object
369318fe57SMatthew G. Knepley 
379318fe57SMatthew G. Knepley   Output Parameter:
389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
399318fe57SMatthew G. Knepley 
409318fe57SMatthew G. Knepley   Level: intermediate
419318fe57SMatthew G. Knepley 
42a1cb98faSBarry Smith   Note:
43a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
44a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
45a1cb98faSBarry Smith 
461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
479318fe57SMatthew G. Knepley @*/
48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
49d71ae5a4SJacob Faibussowitsch {
509318fe57SMatthew G. Knepley   DMPolytopeType ct;
519318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
529318fe57SMatthew G. Knepley 
539318fe57SMatthew G. Knepley   PetscFunctionBegin;
549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
559371c9d4SSatish Balay   if (cEnd <= cStart) {
569371c9d4SSatish Balay     *simplex = PETSC_FALSE;
573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
589371c9d4SSatish Balay   }
599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
609318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629318fe57SMatthew G. Knepley }
639318fe57SMatthew G. Knepley 
649318fe57SMatthew G. Knepley /*@
65412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
66e5337592SStefano Zampini 
67d8d19677SJose E. Roman   Input Parameters:
68a1cb98faSBarry Smith + dm     - The `DMPLEX` object
69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
70e5337592SStefano Zampini 
71e5337592SStefano Zampini   Output Parameters:
72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
7340196513SBarry Smith - cEnd   - The upper bound on "normal" cells
74e5337592SStefano Zampini 
75412e9a14SMatthew G. Knepley   Level: developer
76e5337592SStefano Zampini 
77a1cb98faSBarry Smith   Note:
785ae96e2bSMatthew G. Knepley   This function requires that tensor cells are ordered last.
79a1cb98faSBarry Smith 
802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()`
81e5337592SStefano Zampini @*/
82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
83d71ae5a4SJacob Faibussowitsch {
845ae96e2bSMatthew G. Knepley   DMLabel         ctLabel;
855ae96e2bSMatthew G. Knepley   IS              valueIS;
865ae96e2bSMatthew G. Knepley   const PetscInt *ctypes;
875ae96e2bSMatthew G. Knepley   PetscInt        Nct, cS = PETSC_MAX_INT, cE = 0;
88e5337592SStefano Zampini 
89e5337592SStefano Zampini   PetscFunctionBegin;
909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
915ae96e2bSMatthew G. Knepley   PetscCall(DMLabelGetValueIS(ctLabel, &valueIS));
925ae96e2bSMatthew G. Knepley   PetscCall(ISGetLocalSize(valueIS, &Nct));
935ae96e2bSMatthew G. Knepley   PetscCall(ISGetIndices(valueIS, &ctypes));
945ae96e2bSMatthew G. Knepley   if (!Nct) cS = cE = 0;
955ae96e2bSMatthew G. Knepley   for (PetscInt t = 0; t < Nct; ++t) {
96c306944fSJed Brown     const DMPolytopeType ct = (DMPolytopeType)ctypes[t];
975ae96e2bSMatthew G. Knepley     PetscInt             ctS, ctE, ht;
985ae96e2bSMatthew G. Knepley 
995ae96e2bSMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) {
1005ae96e2bSMatthew G. Knepley       // If any cells are not typed, just use all cells
1015ae96e2bSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd));
1025ae96e2bSMatthew G. Knepley       break;
1035ae96e2bSMatthew G. Knepley     }
104c306944fSJed Brown     if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue;
1055ae96e2bSMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE));
1065ae96e2bSMatthew G. Knepley     if (ctS >= ctE) continue;
1075ae96e2bSMatthew G. Knepley     // Check that a point has the right height
1085ae96e2bSMatthew G. Knepley     PetscCall(DMPlexGetPointHeight(dm, ctS, &ht));
1095ae96e2bSMatthew G. Knepley     if (ht != height) continue;
1105ae96e2bSMatthew G. Knepley     cS = PetscMin(cS, ctS);
1115ae96e2bSMatthew G. Knepley     cE = PetscMax(cE, ctE);
1125ae96e2bSMatthew G. Knepley   }
1135ae96e2bSMatthew G. Knepley   PetscCall(ISDestroy(&valueIS));
114695799ffSMatthew G. Knepley   // Reset label for fast lookup
115695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
116412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
117412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119e5337592SStefano Zampini }
120e5337592SStefano Zampini 
1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft)
1229c600e38SMatt McGurn {
1239c600e38SMatt McGurn   PetscInt                 cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t;
1249c600e38SMatt McGurn   PetscInt                *sStart, *sEnd;
1259c600e38SMatt McGurn   PetscViewerVTKFieldType *ft;
1269c600e38SMatt McGurn   PetscInt                 vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1];
1279c600e38SMatt McGurn   DMLabel                  depthLabel, ctLabel;
1289c600e38SMatt McGurn 
1299c600e38SMatt McGurn   PetscFunctionBegin;
1309c600e38SMatt McGurn   /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */
1319c600e38SMatt McGurn   PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1));
1329c600e38SMatt McGurn   PetscCall(DMGetCoordinateDim(dm, &cdim));
1339c600e38SMatt McGurn   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1349c600e38SMatt McGurn   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1359c600e38SMatt McGurn   if (field >= 0) {
1369c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES]));
1379c600e38SMatt McGurn   } else {
1389c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES]));
1399c600e38SMatt McGurn   }
1409c600e38SMatt McGurn 
1419c600e38SMatt McGurn   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
1429c600e38SMatt McGurn   PetscCall(DMPlexGetDepth(dm, &depth));
1439c600e38SMatt McGurn   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
1449c600e38SMatt McGurn   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1459c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1469c600e38SMatt McGurn     const DMPolytopeType ict = (DMPolytopeType)c;
1479c600e38SMatt McGurn     PetscInt             dep;
1489c600e38SMatt McGurn 
1499c600e38SMatt McGurn     if (ict == DM_POLYTOPE_FV_GHOST) continue;
1509c600e38SMatt McGurn     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1519c600e38SMatt McGurn     if (pStart >= 0) {
1529c600e38SMatt McGurn       PetscCall(DMLabelGetValue(depthLabel, cStart, &dep));
1539c600e38SMatt McGurn       if (dep != depth - cellHeight) continue;
1549c600e38SMatt McGurn     }
1559c600e38SMatt McGurn     if (field >= 0) {
1569c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c]));
1579c600e38SMatt McGurn     } else {
1589c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c]));
1599c600e38SMatt McGurn     }
1609c600e38SMatt McGurn   }
1619c600e38SMatt McGurn 
1629c600e38SMatt McGurn   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1639c600e38SMatt McGurn   *types = 0;
1649c600e38SMatt McGurn 
1659c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) {
1669c600e38SMatt McGurn     if (globalvcdof[c]) ++(*types);
1679c600e38SMatt McGurn   }
1689c600e38SMatt McGurn 
1699c600e38SMatt McGurn   PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft));
1709c600e38SMatt McGurn   t = 0;
1719c600e38SMatt McGurn   if (globalvcdof[DM_NUM_POLYTOPES]) {
1729c600e38SMatt McGurn     sStart[t] = vStart;
1739c600e38SMatt McGurn     sEnd[t]   = vEnd;
1749c600e38SMatt McGurn     ft[t]     = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
1759c600e38SMatt McGurn     ++t;
1769c600e38SMatt McGurn   }
1779c600e38SMatt McGurn 
1789c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1799c600e38SMatt McGurn     if (globalvcdof[c]) {
1809c600e38SMatt McGurn       const DMPolytopeType ict = (DMPolytopeType)c;
1819c600e38SMatt McGurn 
1829c600e38SMatt McGurn       PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1839c600e38SMatt McGurn       sStart[t] = cStart;
1849c600e38SMatt McGurn       sEnd[t]   = cEnd;
1859c600e38SMatt McGurn       ft[t]     = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD;
1869c600e38SMatt McGurn       ++t;
1879c600e38SMatt McGurn     }
1889c600e38SMatt McGurn   }
1899c600e38SMatt McGurn 
1904ad8454bSPierre Jolivet   if (!*types) {
1919c600e38SMatt McGurn     if (field >= 0) {
1929c600e38SMatt McGurn       const char *fieldname;
1939c600e38SMatt McGurn 
1949c600e38SMatt McGurn       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1959c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
1969c600e38SMatt McGurn     } else {
1979c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
1989c600e38SMatt McGurn     }
1999c600e38SMatt McGurn   }
2009c600e38SMatt McGurn 
2019c600e38SMatt McGurn   *ssStart = sStart;
2029c600e38SMatt McGurn   *ssEnd   = sEnd;
2039c600e38SMatt McGurn   *sft     = ft;
2049c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2059c600e38SMatt McGurn }
2069c600e38SMatt McGurn 
2079c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft)
2089c600e38SMatt McGurn {
2099c600e38SMatt McGurn   PetscFunctionBegin;
2109c600e38SMatt McGurn   PetscCall(PetscFree3(*sStart, *sEnd, *ft));
2119c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2129c600e38SMatt McGurn }
2139c600e38SMatt McGurn 
214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
215d71ae5a4SJacob Faibussowitsch {
216412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
217a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
2187e42fee7SMatthew G. Knepley 
2197e42fee7SMatthew G. Knepley   PetscFunctionBegin;
220e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
2219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
2229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
2249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
2257e42fee7SMatthew G. Knepley   if (field >= 0) {
2269566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
2279566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
2287e42fee7SMatthew G. Knepley   } else {
2299566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
2309566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
2317e42fee7SMatthew G. Knepley   }
232712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
233a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
2347e42fee7SMatthew G. Knepley     *sStart = vStart;
2357e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
236f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
2377e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
238a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
2397e42fee7SMatthew G. Knepley     *sStart = cStart;
2407e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
241f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
2427e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
243e630c359SToby Isaac   } else {
244e630c359SToby Isaac     if (field >= 0) {
245e630c359SToby Isaac       const char *fieldname;
246e630c359SToby Isaac 
2479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
24863a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
249e630c359SToby Isaac     } else {
25063a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
251e630c359SToby Isaac     }
252e630c359SToby Isaac   }
2533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2547e42fee7SMatthew G. Knepley }
2557e42fee7SMatthew G. Knepley 
2566913077dSMatthew G. Knepley /*@
2576913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
2586913077dSMatthew G. Knepley 
25920f4b53cSBarry Smith   Collective
2606913077dSMatthew G. Knepley 
2616913077dSMatthew G. Knepley   Input Parameters:
262a1cb98faSBarry Smith + dm     - The `DMPLEX` object
2636913077dSMatthew G. Knepley . n      - The number of vectors
2646913077dSMatthew G. Knepley . u      - The array of local vectors
265a1cb98faSBarry Smith - viewer - The `PetscViewer`
2666913077dSMatthew G. Knepley 
2676913077dSMatthew G. Knepley   Level: advanced
2686913077dSMatthew G. Knepley 
2691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
2706913077dSMatthew G. Knepley @*/
271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
272d71ae5a4SJacob Faibussowitsch {
2736913077dSMatthew G. Knepley   PetscDS            ds;
2746913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
2756913077dSMatthew G. Knepley   PetscDrawLG        lg;
2766913077dSMatthew G. Knepley   Vec                coordinates;
2776913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
2786913077dSMatthew G. Knepley   PetscReal         *vals;
2796913077dSMatthew G. Knepley   PetscInt          *Nc;
2806913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
2816913077dSMatthew G. Knepley   char             **names;
2826913077dSMatthew G. Knepley 
2836913077dSMatthew G. Knepley   PetscFunctionBegin;
2849566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
2859566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2869566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2886913077dSMatthew G. Knepley 
2899566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2903ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
2919566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
2926913077dSMatthew G. Knepley 
2939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2946913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2956913077dSMatthew G. Knepley     const char *vname;
2966913077dSMatthew G. Knepley 
2979566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
2986913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
2996913077dSMatthew G. Knepley       PetscObject disc;
3006913077dSMatthew G. Knepley       const char *fname;
3016913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
3026913077dSMatthew G. Knepley 
3039566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
3046913077dSMatthew G. Knepley       /* TODO Create names for components */
3056913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
3069566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
307c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
308c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
309c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
3109566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
3116913077dSMatthew G. Knepley       }
3126913077dSMatthew G. Knepley     }
3136913077dSMatthew G. Knepley   }
3149566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
3156913077dSMatthew G. Knepley   /* Just add P_1 support for now */
3169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3179566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3189566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
3199566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
3206913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
3216913077dSMatthew G. Knepley     PetscScalar *x, *svals;
3226913077dSMatthew G. Knepley 
3239566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
3246913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
3259566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
3266913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
3276913077dSMatthew G. Knepley     }
3289566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
3296913077dSMatthew G. Knepley   }
3309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
3319566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
3329566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
3339566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
3346913077dSMatthew G. Knepley 
3359566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
3369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3386913077dSMatthew G. Knepley }
3396913077dSMatthew G. Knepley 
340d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
341d71ae5a4SJacob Faibussowitsch {
3426913077dSMatthew G. Knepley   DM dm;
3436913077dSMatthew G. Knepley 
3446913077dSMatthew G. Knepley   PetscFunctionBegin;
3459566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
3469566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
3473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3486913077dSMatthew G. Knepley }
3496913077dSMatthew G. Knepley 
350d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
351d71ae5a4SJacob Faibussowitsch {
352e412dcbdSMatthew G. Knepley   DM                 dm;
353d1df6f1dSMatthew G. Knepley   PetscSection       s;
354e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
355e412dcbdSMatthew G. Knepley   DM                 cdm;
356e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
357e412dcbdSMatthew G. Knepley   Vec                coordinates;
358c9c77995SMatthew G. Knepley   const PetscScalar *array;
359c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
360339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
3616913077dSMatthew G. Knepley   PetscBool          flg;
362d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
363e412dcbdSMatthew G. Knepley   const char        *name;
364339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
365e412dcbdSMatthew G. Knepley 
366e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
3679566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3689566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3709566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
3719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
3729566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
3739566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
3749566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
378e412dcbdSMatthew G. Knepley 
3799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
3809566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
381e412dcbdSMatthew G. Knepley 
3829566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
383c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
3849566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
385e412dcbdSMatthew G. Knepley 
386d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
387d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
388d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
389d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
390d1df6f1dSMatthew G. Knepley     IS          fis;
391d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
392d1df6f1dSMatthew G. Knepley     const char *fname;
393d1df6f1dSMatthew G. Knepley 
3949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
396d1df6f1dSMatthew G. Knepley 
3979566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
398ad540459SPierre Jolivet     else prefix[0] = '\0';
399d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4009566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
4019566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
4029566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
4039566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
404d1df6f1dSMatthew G. Knepley     }
405d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
406d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
407d1df6f1dSMatthew G. Knepley 
4089566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
40963a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
41063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
4119566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
412d1df6f1dSMatthew G. Knepley 
413d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
4149566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
415339e3443SMatthew G. Knepley       if (!flg) {
4169566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
4179566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
418d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
419339e3443SMatthew G. Knepley       }
420c9c77995SMatthew G. Knepley 
4219566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
4229566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
423c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
4249566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
425e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
42699a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
427c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
428c9c77995SMatthew G. Knepley         PetscBool          isDG;
429e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
430e412dcbdSMatthew G. Knepley 
4319566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
432339e3443SMatthew G. Knepley         if (a) {
433d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
434339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
435339e3443SMatthew G. Knepley         } else {
436339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
437339e3443SMatthew G. Knepley           PetscInt     numVals, va;
438339e3443SMatthew G. Knepley 
4399566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
44063a3b9bcSJacob Faibussowitsch           PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals);
441d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
442d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
443d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
444d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
445339e3443SMatthew G. Knepley             break;
446d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
447d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
448d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / (Nc * 2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp + numVals / (Nc * 2)]), vbound[0], vbound[1]);
449d1df6f1dSMatthew G. Knepley             break;
450d71ae5a4SJacob Faibussowitsch           default:
451d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
452339e3443SMatthew G. Knepley           }
4539566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
454339e3443SMatthew G. Knepley         }
455c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
456e412dcbdSMatthew G. Knepley         switch (numCoords) {
457e412dcbdSMatthew G. Knepley         case 6:
4589edc3542SMatthew Knepley         case 12: /* Localized triangle */
4599566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
460e412dcbdSMatthew G. Knepley           break;
461e412dcbdSMatthew G. Knepley         case 8:
4629edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
4639566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
4649566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]));
465e412dcbdSMatthew G. Knepley           break;
466d71ae5a4SJacob Faibussowitsch         default:
467d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
468e412dcbdSMatthew G. Knepley         }
469c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
470e412dcbdSMatthew G. Knepley       }
4719566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
4729566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
4739566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
4749566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
475d1df6f1dSMatthew G. Knepley     }
476d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4779566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
4789566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
4799566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
480d1df6f1dSMatthew G. Knepley     }
481d1df6f1dSMatthew G. Knepley   }
4823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
483e412dcbdSMatthew G. Knepley }
484e412dcbdSMatthew G. Knepley 
485d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
486d71ae5a4SJacob Faibussowitsch {
4876913077dSMatthew G. Knepley   DM        dm;
4886913077dSMatthew G. Knepley   PetscDraw draw;
4896913077dSMatthew G. Knepley   PetscInt  dim;
4906913077dSMatthew G. Knepley   PetscBool isnull;
4916913077dSMatthew G. Knepley 
4926913077dSMatthew G. Knepley   PetscFunctionBegin;
4939566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4949566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4953ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4966913077dSMatthew G. Knepley 
4979566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
4996913077dSMatthew G. Knepley   switch (dim) {
500d71ae5a4SJacob Faibussowitsch   case 1:
501d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
502d71ae5a4SJacob Faibussowitsch     break;
503d71ae5a4SJacob Faibussowitsch   case 2:
504d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
505d71ae5a4SJacob Faibussowitsch     break;
506d71ae5a4SJacob Faibussowitsch   default:
507d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
5086913077dSMatthew G. Knepley   }
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5106913077dSMatthew G. Knepley }
5116913077dSMatthew G. Knepley 
512d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
513d71ae5a4SJacob Faibussowitsch {
514684b87d9SLisandro Dalcin   DM                      dm;
515684b87d9SLisandro Dalcin   Vec                     locv;
516684b87d9SLisandro Dalcin   const char             *name;
517684b87d9SLisandro Dalcin   PetscSection            section;
518684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
519e630c359SToby Isaac   PetscInt                numFields;
520684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
521684b87d9SLisandro Dalcin 
522684b87d9SLisandro Dalcin   PetscFunctionBegin;
5239566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5249566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
5259566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
5279566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
5289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
5299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
530e630c359SToby Isaac   if (!numFields) {
5319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
5329566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
533e630c359SToby Isaac   } else {
534e630c359SToby Isaac     PetscInt f;
535e630c359SToby Isaac 
536e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
5379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
538e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
5399566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
5409566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
541e630c359SToby Isaac     }
5429566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
543e630c359SToby Isaac   }
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
545684b87d9SLisandro Dalcin }
546684b87d9SLisandro Dalcin 
547d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
548d71ae5a4SJacob Faibussowitsch {
549552f7358SJed Brown   DM        dm;
5505f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
551552f7358SJed Brown 
552552f7358SJed Brown   PetscFunctionBegin;
5539566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
55428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5595f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5605f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
561684b87d9SLisandro Dalcin     PetscInt    i, numFields;
562684b87d9SLisandro Dalcin     PetscObject fe;
563ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
564684b87d9SLisandro Dalcin     Vec         locv = v;
565684b87d9SLisandro Dalcin     const char *name;
566684b87d9SLisandro Dalcin     PetscInt    step;
567684b87d9SLisandro Dalcin     PetscReal   time;
568ef31f671SMatthew G. Knepley 
5699566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
570684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
5719566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
5729371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
5739371c9d4SSatish Balay         fem = PETSC_TRUE;
5749371c9d4SSatish Balay         break;
5759371c9d4SSatish Balay       }
576ef31f671SMatthew G. Knepley     }
577684b87d9SLisandro Dalcin     if (fem) {
578798534f6SMatthew G. Knepley       PetscObject isZero;
579798534f6SMatthew G. Knepley 
5809566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
5819566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
5829566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
5839566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5849566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5859566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
5869566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
5879566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
588ef31f671SMatthew G. Knepley     }
589552f7358SJed Brown     if (isvtk) {
5909566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
591b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
592b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5939566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
594b136c2c9SMatthew G. Knepley #else
595b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
596b136c2c9SMatthew G. Knepley #endif
597f13a32a3SMatthew G. Knepley     } else if (isdraw) {
5989566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
599684b87d9SLisandro Dalcin     } else if (isglvis) {
6009566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
6019566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
6029566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
6035f34f2dcSJed Brown     } else if (iscgns) {
6045f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
6055f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
6065f34f2dcSJed Brown #else
6075f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
6085f34f2dcSJed Brown #endif
609684b87d9SLisandro Dalcin     }
610798534f6SMatthew G. Knepley     if (fem) {
6119566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6129566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
613798534f6SMatthew G. Knepley     }
614552f7358SJed Brown   } else {
615684b87d9SLisandro Dalcin     PetscBool isseq;
616684b87d9SLisandro Dalcin 
6179566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6189566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6199566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
620552f7358SJed Brown   }
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622552f7358SJed Brown }
623552f7358SJed Brown 
624d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
625d71ae5a4SJacob Faibussowitsch {
626552f7358SJed Brown   DM        dm;
6275f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
628552f7358SJed Brown 
629552f7358SJed Brown   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
6365f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6385f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
639552f7358SJed Brown     Vec         locv;
640798534f6SMatthew G. Knepley     PetscObject isZero;
641552f7358SJed Brown     const char *name;
642552f7358SJed Brown 
6439566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
6449566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6459566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
6469566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6479566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6489566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6499566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6509566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
6519566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6529566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
653b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
654b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6559566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
656b136c2c9SMatthew G. Knepley #else
657b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
658b136c2c9SMatthew G. Knepley #endif
6596823f3c5SBlaise Bourdin   } else if (isexodusii) {
6606823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6619566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
6626823f3c5SBlaise Bourdin #else
6636823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6646823f3c5SBlaise Bourdin #endif
665552f7358SJed Brown   } else {
666684b87d9SLisandro Dalcin     PetscBool isseq;
667684b87d9SLisandro Dalcin 
6689566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6699566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6709566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
671552f7358SJed Brown   }
6723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
673552f7358SJed Brown }
674552f7358SJed Brown 
675d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
676d71ae5a4SJacob Faibussowitsch {
677d930f514SMatthew G. Knepley   DM                dm;
678d930f514SMatthew G. Knepley   MPI_Comm          comm;
679d930f514SMatthew G. Knepley   PetscViewerFormat format;
680d930f514SMatthew G. Knepley   Vec               v;
681d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
682d930f514SMatthew G. Knepley 
683d930f514SMatthew G. Knepley   PetscFunctionBegin;
6849566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
6859566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
68628b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6879566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
690d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
691a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
692a8ad634aSStefano Zampini     /* this need a better fix */
693a8ad634aSStefano Zampini     if (dm->useNatural) {
694a8ad634aSStefano Zampini       if (dm->sfNatural) {
695d930f514SMatthew G. Knepley         const char *vecname;
696d930f514SMatthew G. Knepley         PetscInt    n, nroots;
697d930f514SMatthew G. Knepley 
6989566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
6999566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
700d930f514SMatthew G. Knepley         if (n == nroots) {
701f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7029566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
7039566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
7049566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7059566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
706d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
707d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
708a8ad634aSStefano Zampini     } else v = originalv;
709a8ad634aSStefano Zampini   } else v = originalv;
710a8ad634aSStefano Zampini 
711d930f514SMatthew G. Knepley   if (ishdf5) {
712d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7139566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
714d930f514SMatthew G. Knepley #else
715d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
716d930f514SMatthew G. Knepley #endif
717d930f514SMatthew G. Knepley   } else if (isvtk) {
718d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
719d930f514SMatthew G. Knepley   } else {
720d930f514SMatthew G. Knepley     PetscBool isseq;
721d930f514SMatthew G. Knepley 
7229566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7239566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
7249566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
725d930f514SMatthew G. Knepley   }
726f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
728d930f514SMatthew G. Knepley }
729d930f514SMatthew G. Knepley 
730d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
731d71ae5a4SJacob Faibussowitsch {
7322c40f234SMatthew G. Knepley   DM        dm;
7332c40f234SMatthew G. Knepley   PetscBool ishdf5;
7342c40f234SMatthew G. Knepley 
7352c40f234SMatthew G. Knepley   PetscFunctionBegin;
7369566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
73728b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7392c40f234SMatthew G. Knepley   if (ishdf5) {
7402c40f234SMatthew G. Knepley     DM          dmBC;
7412c40f234SMatthew G. Knepley     Vec         gv;
7422c40f234SMatthew G. Knepley     const char *name;
7432c40f234SMatthew G. Knepley 
7449566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
7459566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
7469566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
7479566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
7489566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
7499566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
7509566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
7519566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
7521baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7542c40f234SMatthew G. Knepley }
7552c40f234SMatthew G. Knepley 
756d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
757d71ae5a4SJacob Faibussowitsch {
7582c40f234SMatthew G. Knepley   DM        dm;
7596823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
7602c40f234SMatthew G. Knepley 
7612c40f234SMatthew G. Knepley   PetscFunctionBegin;
7629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
76328b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
7662c40f234SMatthew G. Knepley   if (ishdf5) {
767878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7689566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
769b136c2c9SMatthew G. Knepley #else
770b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
771878b459fSMatthew G. Knepley #endif
7726823f3c5SBlaise Bourdin   } else if (isexodusii) {
7736823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
7749566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
7756823f3c5SBlaise Bourdin #else
7766823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
7776823f3c5SBlaise Bourdin #endif
7781baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
780552f7358SJed Brown }
781552f7358SJed Brown 
782d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
783d71ae5a4SJacob Faibussowitsch {
784d930f514SMatthew G. Knepley   DM                dm;
785d930f514SMatthew G. Knepley   PetscViewerFormat format;
786d930f514SMatthew G. Knepley   PetscBool         ishdf5;
787d930f514SMatthew G. Knepley 
788d930f514SMatthew G. Knepley   PetscFunctionBegin;
7899566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
79028b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7919566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
793d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
794a8ad634aSStefano Zampini     if (dm->useNatural) {
795d930f514SMatthew G. Knepley       if (dm->sfNatural) {
796d930f514SMatthew G. Knepley         if (ishdf5) {
797d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
798d930f514SMatthew G. Knepley           Vec         v;
799d930f514SMatthew G. Knepley           const char *vecname;
800d930f514SMatthew G. Knepley 
801f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
8029566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
8039566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
8049566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
8059566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
8069566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
807f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
808d930f514SMatthew G. Knepley #else
809d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
810d930f514SMatthew G. Knepley #endif
811d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
812d930f514SMatthew G. Knepley       }
8131baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
814d930f514SMatthew G. Knepley   }
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
816d930f514SMatthew G. Knepley }
817d930f514SMatthew G. Knepley 
818d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
819d71ae5a4SJacob Faibussowitsch {
820731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
821731e8ddeSMatthew G. Knepley   Vec                coordinates;
822ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
823731e8ddeSMatthew G. Knepley   const char        *name[4];
824731e8ddeSMatthew G. Knepley   const PetscScalar *a;
825731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
826731e8ddeSMatthew G. Knepley 
827731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
8289566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8299566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
8329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
8339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8359566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
836731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
837731e8ddeSMatthew G. Knepley   name[1]       = "edge";
838731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
839731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
840731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
841731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
842ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
843731e8ddeSMatthew G. Knepley 
8449566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
84563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
8469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
848731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
849731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
850731e8ddeSMatthew G. Knepley 
851731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
8529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
853731e8ddeSMatthew G. Knepley       if (!dof) continue;
8549566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
8559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
85663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
857731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
8589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
859731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
8609566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
8619566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
862731e8ddeSMatthew G. Knepley         }
8639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
864731e8ddeSMatthew G. Knepley       }
8659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
866731e8ddeSMatthew G. Knepley     }
8679566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
869731e8ddeSMatthew G. Knepley   }
8709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
8713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
872731e8ddeSMatthew G. Knepley }
873731e8ddeSMatthew G. Knepley 
8749371c9d4SSatish Balay typedef enum {
8759371c9d4SSatish Balay   CS_CARTESIAN,
8769371c9d4SSatish Balay   CS_POLAR,
8779371c9d4SSatish Balay   CS_CYLINDRICAL,
8789371c9d4SSatish Balay   CS_SPHERICAL
8799371c9d4SSatish Balay } CoordSystem;
88019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
88119ad8254SMatthew G. Knepley 
882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
883d71ae5a4SJacob Faibussowitsch {
88419ad8254SMatthew G. Knepley   PetscInt i;
88519ad8254SMatthew G. Knepley 
88619ad8254SMatthew G. Knepley   PetscFunctionBegin;
88719ad8254SMatthew G. Knepley   if (dim > 3) {
8889566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
88919ad8254SMatthew G. Knepley   } else {
890bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
89119ad8254SMatthew G. Knepley 
89219ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
89319ad8254SMatthew G. Knepley     switch (cs) {
8949371c9d4SSatish Balay     case CS_CARTESIAN:
8959371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8969371c9d4SSatish Balay       break;
89719ad8254SMatthew G. Knepley     case CS_POLAR:
89863a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
89919ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90019ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90119ad8254SMatthew G. Knepley       break;
90219ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
90363a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
90419ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90519ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90619ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
90719ad8254SMatthew G. Knepley       break;
90819ad8254SMatthew G. Knepley     case CS_SPHERICAL:
90963a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
91019ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
91119ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
91219ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
91319ad8254SMatthew G. Knepley       break;
91419ad8254SMatthew G. Knepley     }
9159566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
91619ad8254SMatthew G. Knepley   }
9173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91819ad8254SMatthew G. Knepley }
91919ad8254SMatthew G. Knepley 
920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
921d71ae5a4SJacob Faibussowitsch {
922552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
9236858538eSMatthew G. Knepley   DM                cdm, cdmCell;
9246858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
9256858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
926552f7358SJed Brown   PetscViewerFormat format;
927552f7358SJed Brown 
928552f7358SJed Brown   PetscFunctionBegin;
9299566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
930552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
931552f7358SJed Brown     const char *name;
932f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
9339318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
934552f7358SJed Brown     PetscMPIInt rank, size;
935552f7358SJed Brown 
9369f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9379f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9389f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9399f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9409f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9419f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9449566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
9459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
9479566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
95063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
95163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
95263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
9539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
95463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
955552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
956552f7358SJed Brown       PetscInt dof, off, s;
957552f7358SJed Brown 
9589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
9599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
96048a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
961552f7358SJed Brown     }
9629566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
96363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
96463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
965552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
966552f7358SJed Brown       PetscInt dof, off, c;
967552f7358SJed Brown 
9689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
9699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
97048a46eb9SPierre Jolivet       for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
971552f7358SJed Brown     }
9729566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
9739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9743d2e540fSStefano Zampini     if (coordSection && coordinates) {
97519ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
9766858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
9776858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
97819ad8254SMatthew G. Knepley       PetscMPIInt        rank;
97919ad8254SMatthew G. Knepley       const char        *name;
98019ad8254SMatthew G. Knepley 
9819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
9829566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
9839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
98463a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
9859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
9866858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
9876858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
9886858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
9896858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
9909566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
99163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
99263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9939566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
99419ad8254SMatthew G. Knepley 
9959566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9966858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
9989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
99919ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
100019ad8254SMatthew G. Knepley         PetscInt dof, off;
100119ad8254SMatthew G. Knepley 
10026858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
10039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
10049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
10056858538eSMatthew G. Knepley           if (dof) {
100663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10079566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
10089566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
100919ad8254SMatthew G. Knepley           }
10106858538eSMatthew G. Knepley         }
10116858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
10126858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
10136858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
10146858538eSMatthew G. Knepley           if (dof) {
10156858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10166858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
10176858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
10186858538eSMatthew G. Knepley           }
10196858538eSMatthew G. Knepley         }
10206858538eSMatthew G. Knepley       }
10219566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
10239566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
10246858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
10253d2e540fSStefano Zampini     }
10269566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10279566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
10289318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
10299318fe57SMatthew G. Knepley       DMLabel     label;
10309318fe57SMatthew G. Knepley       PetscBool   isdepth;
10319318fe57SMatthew G. Knepley       const char *name;
10329318fe57SMatthew G. Knepley 
10339566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
10349566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
10359318fe57SMatthew G. Knepley       if (isdepth) continue;
10369566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
10379566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
10389318fe57SMatthew G. Knepley     }
1039552f7358SJed Brown     if (size > 1) {
1040552f7358SJed Brown       PetscSF sf;
1041552f7358SJed Brown 
10429566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
10439566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
1044552f7358SJed Brown     }
10454e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
10469566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1047552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
10480588280cSMatthew G. Knepley     const char  *name, *color;
10490588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
10500588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
1051fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
1052552f7358SJed Brown     PetscReal    scale      = 2.0;
105378081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
1054b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
10550588280cSMatthew G. Knepley     double       tcoords[3];
1056552f7358SJed Brown     PetscScalar *coords;
1057b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
1058552f7358SJed Brown     PetscMPIInt  rank, size;
10590588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
1060b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
1061fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
1062fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
1063552f7358SJed Brown 
10649f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
10659f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
10669f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10679f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
10689f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
10699f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
10709566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
10719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
10729566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10730588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
10740588280cSMatthew G. Knepley     numColors  = 10;
10750588280cSMatthew G. Knepley     numLColors = 10;
10769566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
10779566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
10789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
10799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
1080b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
1081b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
1082b7f6ffafSMatthew G. Knepley     n = 4;
10839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
10841dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
1085bd3611e6SMatthew G. Knepley     n = 4;
10869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
10871dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
10889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
10890588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
10909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
10910588280cSMatthew G. Knepley     if (!useColors) {
10920588280cSMatthew G. Knepley       numColors = 3;
10939566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10940588280cSMatthew G. Knepley     }
10959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10960588280cSMatthew G. Knepley     if (!useColors) {
10970588280cSMatthew G. Knepley       numLColors = 4;
10989566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
10990588280cSMatthew G. Knepley     }
11009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1101b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
11029566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
11031dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1104202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
11059566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1106fe1cc32dSStefano Zampini 
1107fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
11089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1112fe1cc32dSStefano Zampini     if (lflg) {
1113fe1cc32dSStefano Zampini       DMLabel lbl;
1114fe1cc32dSStefano Zampini 
11159566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1116fe1cc32dSStefano Zampini       if (lbl) {
1117fe1cc32dSStefano Zampini         PetscInt val, defval;
1118fe1cc32dSStefano Zampini 
11199566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
11209566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1121fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1122fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1123fe1cc32dSStefano Zampini           PetscInt  closureSize;
1124fe1cc32dSStefano Zampini 
11259566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1126fe1cc32dSStefano Zampini           if (val == defval) continue;
1127fe1cc32dSStefano Zampini 
11289566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
112948a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
11309566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1131fe1cc32dSStefano Zampini         }
1132fe1cc32dSStefano Zampini       }
1133fe1cc32dSStefano Zampini     }
1134fe1cc32dSStefano Zampini 
11359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
11369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
11389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
11390588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1140552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1141552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1142552f7358SJed Brown \\usetikzlibrary{arrows}\n\
11435f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
11440588280cSMatthew G. Knepley     if (size > 1) {
11459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1146770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
114763a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
114863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1149770b213bSMatthew G Knepley       }
11509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
11510588280cSMatthew G. Knepley     }
1152b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1153b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1154b7f6ffafSMatthew G. Knepley 
115563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
115663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
11589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
115963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
116063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
11619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
116263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
116363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
116463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
116563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
11669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1167b7f6ffafSMatthew G. Knepley     }
11689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1169fe1cc32dSStefano Zampini 
1170552f7358SJed Brown     /* Plot vertices */
11719566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
11729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1173552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1174552f7358SJed Brown       PetscInt  off, dof, d;
11750588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1176552f7358SJed Brown 
1177fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
11789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
11799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
11809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
118163a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
11820588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11830588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1184c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
11850588280cSMatthew G. Knepley       }
11860588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
11879371c9d4SSatish Balay       if (dim == 3) {
11889371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
11899371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
11909371c9d4SSatish Balay         tcoords[2]    = -tmp;
11919371c9d4SSatish Balay       }
1192552f7358SJed Brown       for (d = 0; d < dof; ++d) {
11939566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11949566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1195552f7358SJed Brown       }
1196b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1197b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11980588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
11990588280cSMatthew G. Knepley         PetscInt val;
12009566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12019371c9d4SSatish Balay         if (val >= 0) {
12029371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12039371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12049371c9d4SSatish Balay           break;
12059371c9d4SSatish Balay         }
12060588280cSMatthew G. Knepley       }
1207b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
120863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1209b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
121063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
12111baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1212552f7358SJed Brown     }
12139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12149566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1215b7f6ffafSMatthew G. Knepley     /* Plot edges */
1216b7f6ffafSMatthew G. Knepley     if (plotEdges) {
12179566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
12189566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1219b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1220b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1221b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1222b7f6ffafSMatthew G. Knepley 
1223b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
12249566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
122563a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
12269566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
12279566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
12289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
12299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
12309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1231b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1232b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1233b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1234b7f6ffafSMatthew G. Knepley         }
1235b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12369371c9d4SSatish Balay         if (dim == 3) {
12379371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12389371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12399371c9d4SSatish Balay           tcoords[2]    = -tmp;
12409371c9d4SSatish Balay         }
1241b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12429566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12439566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1244b7f6ffafSMatthew G. Knepley         }
1245b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1246b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1247b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1248b7f6ffafSMatthew G. Knepley           PetscInt val;
1249bd3611e6SMatthew G. Knepley           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12509371c9d4SSatish Balay           if (val >= 0) {
12519371c9d4SSatish Balay             color = lcolors[l % numLColors];
12529371c9d4SSatish Balay             break;
12539371c9d4SSatish Balay           }
1254b7f6ffafSMatthew G. Knepley         }
125563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1256b7f6ffafSMatthew G. Knepley       }
12579566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
12589566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1260b7f6ffafSMatthew G. Knepley     }
1261846a3e8bSMatthew G. Knepley     /* Plot cells */
1262b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1263846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1264846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1265846a3e8bSMatthew G. Knepley 
1266fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1267846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1268846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1269846a3e8bSMatthew G. Knepley           PetscInt val;
12709566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12719371c9d4SSatish Balay           if (val >= 0) {
12729371c9d4SSatish Balay             color = lcolors[l % numLColors];
12739371c9d4SSatish Balay             break;
12749371c9d4SSatish Balay           }
1275846a3e8bSMatthew G. Knepley         }
12769566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
127763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1278846a3e8bSMatthew G. Knepley       }
1279846a3e8bSMatthew G. Knepley     } else {
1280b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1281846a3e8bSMatthew G. Knepley 
1282b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1283b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1284fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
12859566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1286c306944fSJed Brown         if (DMPolytopeTypeIsHybrid(ct)) {
1287b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1288b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1289b7f6ffafSMatthew G. Knepley 
12909566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
12919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1292b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1293b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1294b7f6ffafSMatthew G. Knepley 
12959566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
129663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1297b7f6ffafSMatthew G. Knepley           }
1298b7f6ffafSMatthew G. Knepley         } else {
1299b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1300b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1301b7f6ffafSMatthew G. Knepley 
13029566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1303846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1304846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1305846a3e8bSMatthew G. Knepley 
1306b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1307846a3e8bSMatthew G. Knepley           }
13089566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1309b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1310b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1311b7f6ffafSMatthew G. Knepley 
1312b7f6ffafSMatthew G. Knepley             if (v > 0) {
1313b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1314b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1315b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1316b7f6ffafSMatthew G. Knepley 
13179371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
13189371c9d4SSatish Balay                 endpoints[1] = vertex;
13199566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
132063a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
132163a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
13229566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
13231baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1324b7f6ffafSMatthew G. Knepley             }
132563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1326b7f6ffafSMatthew G. Knepley           }
13279566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
13289566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1329846a3e8bSMatthew G. Knepley         }
1330846a3e8bSMatthew G. Knepley       }
1331b7f6ffafSMatthew G. Knepley     }
1332846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1333846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1334846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1335c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1336c713ec31SMatthew G. Knepley       const PetscScalar *array;
1337c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1338c713ec31SMatthew G. Knepley       PetscBool          isDG;
1339846a3e8bSMatthew G. Knepley 
1340fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1341c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1342c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1343c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
13449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1345c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1346c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1347c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1348846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1349846a3e8bSMatthew G. Knepley         }
1350846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
13519371c9d4SSatish Balay         if (cdim == 3) {
13529371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
13539371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
13549371c9d4SSatish Balay           tcoords[2]    = -tmp;
13559371c9d4SSatish Balay         }
1356ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1357846a3e8bSMatthew G. Knepley       }
1358ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1359c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1360c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
13619566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
13629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1363846a3e8bSMatthew G. Knepley       }
1364b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1365b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1366846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1367846a3e8bSMatthew G. Knepley         PetscInt val;
13689566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
13699371c9d4SSatish Balay         if (val >= 0) {
13709371c9d4SSatish Balay           color     = lcolors[l % numLColors];
13719371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
13729371c9d4SSatish Balay           break;
13739371c9d4SSatish Balay         }
1374846a3e8bSMatthew G. Knepley       }
1375b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
137663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1377b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
137863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
13791baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1380846a3e8bSMatthew G. Knepley     }
1381b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1382b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
13839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
13849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1388552f7358SJed Brown 
1389b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
13909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
13919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
13929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1395b7f6ffafSMatthew G. Knepley 
1396b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
13999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
14009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
14019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1402b7f6ffafSMatthew G. Knepley 
1403b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1404b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1405b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1406b7f6ffafSMatthew G. Knepley 
14079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
14089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
140948a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
14100588280cSMatthew G. Knepley       }
14110588280cSMatthew G. Knepley     }
14129566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
14139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
14149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
141563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
14169566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
14179566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
14189566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
14199566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
14209566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
14210f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
14220f7d6e4aSStefano Zampini     Vec                    cown, acown;
14230f7d6e4aSStefano Zampini     VecScatter             sct;
14240f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
14250f7d6e4aSStefano Zampini     IS                     gid, acis;
14260f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
14270f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
14280f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
14290f7d6e4aSStefano Zampini     const PetscInt        *idxs;
14300f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
14310f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
14320f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
14330f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
14340f7d6e4aSStefano Zampini 
14359566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1437b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
14389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
14390f7d6e4aSStefano Zampini #endif
14400f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
14419566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
14429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
14430f7d6e4aSStefano Zampini       d1 = 0;
14449566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
14450f7d6e4aSStefano Zampini       nid = d2;
14469566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
14479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
14489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
14490f7d6e4aSStefano Zampini     } else nid = 0.0;
14500f7d6e4aSStefano Zampini 
14510f7d6e4aSStefano Zampini     /* Get connectivity */
14529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14539566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
14540f7d6e4aSStefano Zampini 
14550f7d6e4aSStefano Zampini     /* filter overlapped local cells */
14569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
14579566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
14589566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
14599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
14600f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
14610f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
14620f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
14630f7d6e4aSStefano Zampini     }
14649566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
146563a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
14669566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14679566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
14680f7d6e4aSStefano Zampini 
14690f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
14709566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
14719566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
14729566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
14739566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
14740f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
14759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
14769566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
14779566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14789566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
14809566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
14819566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
14820f7d6e4aSStefano Zampini 
14830f7d6e4aSStefano Zampini     /* compute edgeCut */
14840f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
14859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
14869566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
14879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
14889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14899566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
14900f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
14910f7d6e4aSStefano Zampini       PetscInt totl;
14920f7d6e4aSStefano Zampini 
14930f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14949566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14950f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14960f7d6e4aSStefano Zampini         if (work[i] < 0) {
14970f7d6e4aSStefano Zampini           ect += 1;
14980f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
14990f7d6e4aSStefano Zampini         }
15000f7d6e4aSStefano Zampini       }
15010f7d6e4aSStefano Zampini     }
15029566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
15039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
15040f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
15050f7d6e4aSStefano Zampini     lm[1] = -numVertices;
15061c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
150763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0]));
15080f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
15090f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
15100f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
15111c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
151263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1513b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1514f4f49eeaSPierre Jolivet     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.));
15150f7d6e4aSStefano Zampini #else
151663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
15170f7d6e4aSStefano Zampini #endif
15189566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
15199566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
15219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1522552f7358SJed Brown   } else {
1523412e9a14SMatthew G. Knepley     const char    *name;
1524d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1525412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1526d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1527ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
15289318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1529412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1530412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1531552f7358SJed Brown 
15329566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
15349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
15359566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
15369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15379566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
153863a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
153963a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
154063a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
15419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
15421c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
15432827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1544d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
15459566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
15469566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1547412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1548412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1549412e9a14SMatthew G. Knepley 
15509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
15519566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1552412e9a14SMatthew G. Knepley       ict = ct0;
15539566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1554412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1555412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1556412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1557412e9a14SMatthew G. Knepley 
15589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1559412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1560412e9a14SMatthew G. Knepley         else ++Nc[1];
1561412e9a14SMatthew G. Knepley       }
1562ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
15639566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
15659566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
156663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1567834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1568dd400576SPatrick Sanan           if (rank == 0) {
156963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
157063a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
157163a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1572834065abSMatthew G. Knepley           }
1573cbb7f117SMark Adams         }
1574ca7bf7eeSMatthew G. Knepley       } else {
1575ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1576ca7bf7eeSMatthew G. Knepley 
15779371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
15789371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
15799566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15809371c9d4SSatish Balay         locMinMax[0] = Nc[1];
15819371c9d4SSatish Balay         locMinMax[1] = Nc[1];
15829566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1583ca7bf7eeSMatthew G. Knepley         if (d == depth) {
15849371c9d4SSatish Balay           locMinMax[0] = gcNum;
15859371c9d4SSatish Balay           locMinMax[1] = gcNum;
15869566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1587ca7bf7eeSMatthew G. Knepley         }
158863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
15899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15909566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
15919566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1592ca7bf7eeSMatthew G. Knepley       }
15939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1594552f7358SJed Brown     }
15959566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15969318fe57SMatthew G. Knepley     {
15979318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15989318fe57SMatthew G. Knepley       const PetscReal *L;
15996858538eSMatthew G. Knepley       PetscBool        localized;
16009318fe57SMatthew G. Knepley 
16014fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
16029566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
16036858538eSMatthew G. Knepley       if (L || localized) {
16046858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
16059566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
16066858538eSMatthew G. Knepley         if (L) {
16076858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
16089318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
16096858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
16106858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
16119318fe57SMatthew G. Knepley           }
16126858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
16136858538eSMatthew G. Knepley         }
16146858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
16159566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16169318fe57SMatthew G. Knepley       }
16179318fe57SMatthew G. Knepley     }
16189566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
16199566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1620a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1621a57dd577SMatthew G Knepley       DMLabel         label;
1622a57dd577SMatthew G Knepley       const char     *name;
1623a57dd577SMatthew G Knepley       IS              valueIS;
1624a57dd577SMatthew G Knepley       const PetscInt *values;
1625a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1626a57dd577SMatthew G Knepley 
16279566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
16289566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
16299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
163063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
16319566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
16329566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
16339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1634a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1635a57dd577SMatthew G Knepley         PetscInt size;
1636a57dd577SMatthew G Knepley 
16379566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
16389566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
163963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1640a57dd577SMatthew G Knepley       }
16419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
16429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16439566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
16449566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1645a57dd577SMatthew G Knepley     }
1646c1cad2e7SMatthew G. Knepley     {
1647c1cad2e7SMatthew G. Knepley       char    **labelNames;
1648c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1649c1cad2e7SMatthew G. Knepley       PetscBool flg;
1650c1cad2e7SMatthew G. Knepley 
16519566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
16529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1653c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1654c1cad2e7SMatthew G. Knepley         DMLabel label;
1655c1cad2e7SMatthew G. Knepley 
16569566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1657c1cad2e7SMatthew G. Knepley         if (flg) {
16589566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
16599566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1660c1cad2e7SMatthew G. Knepley         }
16619566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1662c1cad2e7SMatthew G. Knepley       }
16639566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1664c1cad2e7SMatthew G. Knepley     }
166534aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
166634aa8a36SMatthew G. Knepley     if (dm->Nf) {
166734aa8a36SMatthew G. Knepley       PetscInt f;
166834aa8a36SMatthew G. Knepley 
166934aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
167034aa8a36SMatthew G. Knepley         const char *name;
167134aa8a36SMatthew G. Knepley 
16729566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
16739566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
16749566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
16759566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
167634aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
16779566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
16789566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
167934aa8a36SMatthew G. Knepley         } else {
16809566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
16819566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
168234aa8a36SMatthew G. Knepley         }
16839566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
168434aa8a36SMatthew G. Knepley       }
168534aa8a36SMatthew G. Knepley     }
16869566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
16878e7ff633SMatthew G. Knepley     if (cdm) {
16889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
16899f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
16909566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
16919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
16928e7ff633SMatthew G. Knepley     }
1693552f7358SJed Brown   }
16943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1695552f7358SJed Brown }
1696552f7358SJed Brown 
1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1698d71ae5a4SJacob Faibussowitsch {
1699e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1700e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1701a12d352dSMatthew G. Knepley   PetscInt       cdim;
1702e5c487bfSMatthew G. Knepley 
1703e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
17069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1707e5c487bfSMatthew G. Knepley   switch (ct) {
1708a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1709a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1710a12d352dSMatthew G. Knepley     switch (cdim) {
17119371c9d4SSatish Balay     case 1: {
1712a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1713a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1714a12d352dSMatthew G. Knepley 
17159566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
17169566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
17179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
17189371c9d4SSatish Balay     } break;
17199371c9d4SSatish Balay     case 2: {
1720a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1721a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1722a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1723a12d352dSMatthew G. Knepley 
17249566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17259566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK));
17269566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK));
17279371c9d4SSatish Balay     } break;
1728d71ae5a4SJacob Faibussowitsch     default:
1729d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1730a12d352dSMatthew G. Knepley     }
1731a12d352dSMatthew G. Knepley     break;
1732e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
17339371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17349566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1737e5c487bfSMatthew G. Knepley     break;
1738e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
17399371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17409371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1745e5c487bfSMatthew G. Knepley     break;
17469f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
17479f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17489f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17519f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17529f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
17539f4ada15SMatthew G. Knepley     break;
1754d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1755d71ae5a4SJacob Faibussowitsch     break;
1756d71ae5a4SJacob Faibussowitsch   default:
1757d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1758e5c487bfSMatthew G. Knepley   }
17593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1760e5c487bfSMatthew G. Knepley }
1761e5c487bfSMatthew G. Knepley 
1762c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1763d71ae5a4SJacob Faibussowitsch {
1764e5c487bfSMatthew G. Knepley   PetscReal   centroid[2] = {0., 0.};
1765e5c487bfSMatthew G. Knepley   PetscMPIInt rank;
1766c5aedaa3SMatthew G. Knepley   PetscInt    fillColor;
1767e5c487bfSMatthew G. Knepley 
1768e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1770e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1771c5aedaa3SMatthew G. Knepley   for (PetscInt v = 0; v < Nv; ++v) {
1772c5aedaa3SMatthew G. Knepley     centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv;
1773c5aedaa3SMatthew G. Knepley     centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv;
17749371c9d4SSatish Balay   }
1775c5aedaa3SMatthew G. Knepley   for (PetscInt e = 0; e < Nv; ++e) {
1776e5c487bfSMatthew G. Knepley     refCoords[0] = refVertices[e * 2 + 0];
1777e5c487bfSMatthew G. Knepley     refCoords[1] = refVertices[e * 2 + 1];
1778c5aedaa3SMatthew G. Knepley     for (PetscInt d = 1; d <= edgeDiv; ++d) {
1779c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv;
1780c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv;
1781e5c487bfSMatthew G. Knepley     }
17829566063dSJacob Faibussowitsch     PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1783c5aedaa3SMatthew G. Knepley     for (PetscInt d = 0; d < edgeDiv; ++d) {
17849566063dSJacob Faibussowitsch       PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor));
17859566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK));
1786e5c487bfSMatthew G. Knepley     }
1787e5c487bfSMatthew G. Knepley   }
1788c5aedaa3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1789c5aedaa3SMatthew G. Knepley }
1790c5aedaa3SMatthew G. Knepley 
1791c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1792c5aedaa3SMatthew G. Knepley {
1793c5aedaa3SMatthew G. Knepley   DMPolytopeType ct;
1794c5aedaa3SMatthew G. Knepley 
1795c5aedaa3SMatthew G. Knepley   PetscFunctionBegin;
1796c5aedaa3SMatthew G. Knepley   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1797c5aedaa3SMatthew G. Knepley   switch (ct) {
1798c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE: {
1799c5aedaa3SMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1800c5aedaa3SMatthew G. Knepley 
1801c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords));
1802c5aedaa3SMatthew G. Knepley   } break;
1803c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: {
1804c5aedaa3SMatthew G. Knepley     PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.};
1805c5aedaa3SMatthew G. Knepley 
1806c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords));
18079371c9d4SSatish Balay   } break;
1808d71ae5a4SJacob Faibussowitsch   default:
1809d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1810e5c487bfSMatthew G. Knepley   }
18113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1812e5c487bfSMatthew G. Knepley }
1813e5c487bfSMatthew G. Knepley 
1814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1815d71ae5a4SJacob Faibussowitsch {
1816e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1817e412dcbdSMatthew G. Knepley   DM           cdm;
1818e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1819e412dcbdSMatthew G. Knepley   Vec          coordinates;
1820c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1821e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1822c5aedaa3SMatthew G. Knepley   PetscBool    isnull, drawAffine;
1823c5aedaa3SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv;
1824e412dcbdSMatthew G. Knepley 
1825e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
18269566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
182763a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
1828c5aedaa3SMatthew G. Knepley   PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree));
1829c5aedaa3SMatthew G. Knepley   drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE;
1830c5aedaa3SMatthew G. Knepley   edgeDiv    = cDegree + 1;
18319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
18329566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
18339566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
18349566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
18359566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
18369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1838e412dcbdSMatthew G. Knepley 
18399566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18409566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
18413ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
18429566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1843e412dcbdSMatthew G. Knepley 
1844c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
18459566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1847e412dcbdSMatthew G. Knepley 
1848cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1849cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1850c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1851ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1852c9c77995SMatthew G. Knepley     PetscBool          isDG;
1853cf3064d3SMatthew G. Knepley 
1854c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
18551baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
18561baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1857c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1858cf3064d3SMatthew G. Knepley   }
18599566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
18609566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
18619566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
18629566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
18633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1864e412dcbdSMatthew G. Knepley }
1865e412dcbdSMatthew G. Knepley 
1866e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm)
1867e44f6aebSMatthew G. Knepley {
1868e44f6aebSMatthew G. Knepley   DM           odm = dm, rdm = dm, cdm;
1869e44f6aebSMatthew G. Knepley   PetscFE      fe;
1870e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1871e44f6aebSMatthew G. Knepley   PetscClassId id;
1872e44f6aebSMatthew G. Knepley   PetscInt     degree;
1873e44f6aebSMatthew G. Knepley   PetscBool    hoView = PETSC_TRUE;
1874e44f6aebSMatthew G. Knepley 
1875e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1876e44f6aebSMatthew G. Knepley   PetscObjectOptionsBegin((PetscObject)dm);
1877e44f6aebSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL));
1878e44f6aebSMatthew G. Knepley   PetscOptionsEnd();
1879e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dm));
1880e44f6aebSMatthew G. Knepley   *hdm = dm;
1881e44f6aebSMatthew G. Knepley   if (!hoView) PetscFunctionReturn(PETSC_SUCCESS);
1882e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1883e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1884e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1885e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1886e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1887e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
1888e44f6aebSMatthew G. Knepley   for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) {
1889e44f6aebSMatthew G. Knepley     DM  cdm, rcdm;
1890e44f6aebSMatthew G. Knepley     Mat In;
1891e44f6aebSMatthew G. Knepley     Vec cl, rcl;
1892e44f6aebSMatthew G. Knepley 
1893e44f6aebSMatthew G. Knepley     PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm));
1894c5aedaa3SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL));
1895e44f6aebSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates"));
1896e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(odm, &cdm));
1897e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(rdm, &rcdm));
1898e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(odm, &cl));
1899e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(rdm, &rcl));
1900e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoarseDM(rcdm, cdm));
1901e44f6aebSMatthew G. Knepley     PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL));
1902e44f6aebSMatthew G. Knepley     PetscCall(MatMult(In, cl, rcl));
1903e44f6aebSMatthew G. Knepley     PetscCall(MatDestroy(&In));
1904e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(rdm, rcl));
1905e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&odm));
1906e44f6aebSMatthew G. Knepley     odm = rdm;
1907e44f6aebSMatthew G. Knepley   }
1908e44f6aebSMatthew G. Knepley   *hdm = rdm;
1909e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1910e44f6aebSMatthew G. Knepley }
1911e44f6aebSMatthew G. Knepley 
19121e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19131e50132fSMatthew G. Knepley   #include <exodusII.h>
19146823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
19151e50132fSMatthew G. Knepley #endif
19161e50132fSMatthew G. Knepley 
1917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1918d71ae5a4SJacob Faibussowitsch {
19195f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1920002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1921552f7358SJed Brown 
1922552f7358SJed Brown   PetscFunctionBegin;
1923552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1924552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
19279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
19315f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1932552f7358SJed Brown   if (iascii) {
19338135c375SStefano Zampini     PetscViewerFormat format;
19349566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
19351baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
19361baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1937c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1938c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
19399566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1940c6ccd67eSMatthew G. Knepley #else
1941c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1942552f7358SJed Brown #endif
1943e412dcbdSMatthew G. Knepley   } else if (isvtk) {
19449566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1945e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1946e44f6aebSMatthew G. Knepley     DM hdm;
1947e44f6aebSMatthew G. Knepley 
1948e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm));
1949e44f6aebSMatthew G. Knepley     PetscCall(DMPlexView_Draw(hdm, viewer));
1950e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&hdm));
19518135c375SStefano Zampini   } else if (isglvis) {
19529566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
19531e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19541e50132fSMatthew G. Knepley   } else if (isexodus) {
19556823f3c5SBlaise Bourdin     /*
19566823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
19576823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1958da81f932SPierre Jolivet       with ID 1, containing all cells.
19596823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
19606823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
19616823f3c5SBlaise Bourdin     */
19626823f3c5SBlaise Bourdin     PetscInt numCS;
19639566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
19646823f3c5SBlaise Bourdin     if (!numCS) {
19651e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
19669566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
19679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
19689566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
19696823f3c5SBlaise Bourdin     }
19709566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
19711e50132fSMatthew G. Knepley #endif
19725f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
19735f34f2dcSJed Brown   } else if (iscgns) {
19745f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
19755f34f2dcSJed Brown #endif
19761baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1977cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
19789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1979cb3ba0daSMatthew G. Knepley   if (flg) {
1980cb3ba0daSMatthew G. Knepley     Vec ranks;
19819566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
19829566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
19839566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1984cb3ba0daSMatthew G. Knepley   }
1985002a2709SMatthew G. Knepley   /* Optionally view a label */
19869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1987002a2709SMatthew G. Knepley   if (flg) {
1988002a2709SMatthew G. Knepley     DMLabel label;
1989002a2709SMatthew G. Knepley     Vec     val;
1990002a2709SMatthew G. Knepley 
19919566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
199228b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
19939566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
19949566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
19959566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1996002a2709SMatthew G. Knepley   }
19973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1998552f7358SJed Brown }
1999552f7358SJed Brown 
20007f96f51bSksagiyam /*@
2001a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
20027f96f51bSksagiyam 
200320f4b53cSBarry Smith   Collective
20047f96f51bSksagiyam 
20057f96f51bSksagiyam   Input Parameters:
2006a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
2007a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
20087f96f51bSksagiyam 
20097f96f51bSksagiyam   Level: advanced
20107f96f51bSksagiyam 
20111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
20127f96f51bSksagiyam @*/
2013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
2014d71ae5a4SJacob Faibussowitsch {
20157f96f51bSksagiyam   PetscBool ishdf5;
20167f96f51bSksagiyam 
20177f96f51bSksagiyam   PetscFunctionBegin;
20187f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20197f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
20227f96f51bSksagiyam   if (ishdf5) {
20237f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
20247f96f51bSksagiyam     PetscViewerFormat format;
20259566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20267f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20277f96f51bSksagiyam       IS globalPointNumbering;
20287f96f51bSksagiyam 
20299566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20309566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
20319566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
203298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
20337f96f51bSksagiyam #else
20347f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20357f96f51bSksagiyam #endif
20367f96f51bSksagiyam   }
20379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
20383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20397f96f51bSksagiyam }
20407f96f51bSksagiyam 
204177b8e257Sksagiyam /*@
2042a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
204377b8e257Sksagiyam 
204420f4b53cSBarry Smith   Collective
204577b8e257Sksagiyam 
204677b8e257Sksagiyam   Input Parameters:
2047a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
2048a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
204977b8e257Sksagiyam 
205077b8e257Sksagiyam   Level: advanced
205177b8e257Sksagiyam 
20521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
205377b8e257Sksagiyam @*/
2054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
2055d71ae5a4SJacob Faibussowitsch {
205677b8e257Sksagiyam   PetscBool ishdf5;
205777b8e257Sksagiyam 
205877b8e257Sksagiyam   PetscFunctionBegin;
205977b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
206077b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
206377b8e257Sksagiyam   if (ishdf5) {
206477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
206577b8e257Sksagiyam     PetscViewerFormat format;
20669566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
206777b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20689566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
2069fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
207077b8e257Sksagiyam #else
207177b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
207277b8e257Sksagiyam #endif
207377b8e257Sksagiyam   }
20749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
20753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207677b8e257Sksagiyam }
207777b8e257Sksagiyam 
2078bd6565f1Sksagiyam /*@
2079a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
2080bd6565f1Sksagiyam 
208120f4b53cSBarry Smith   Collective
2082bd6565f1Sksagiyam 
2083bd6565f1Sksagiyam   Input Parameters:
2084a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
2085a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
2086bd6565f1Sksagiyam 
2087bd6565f1Sksagiyam   Level: advanced
2088bd6565f1Sksagiyam 
20891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
2090bd6565f1Sksagiyam @*/
2091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
2092d71ae5a4SJacob Faibussowitsch {
2093bd6565f1Sksagiyam   PetscBool ishdf5;
2094bd6565f1Sksagiyam 
2095bd6565f1Sksagiyam   PetscFunctionBegin;
2096bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2097bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
2100bd6565f1Sksagiyam   if (ishdf5) {
2101bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
2102bd6565f1Sksagiyam     IS                globalPointNumbering;
2103bd6565f1Sksagiyam     PetscViewerFormat format;
2104bd6565f1Sksagiyam 
21059566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2106bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21079566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
21089566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
21099566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
211098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2111bd6565f1Sksagiyam #else
2112bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2113bd6565f1Sksagiyam #endif
2114bd6565f1Sksagiyam   }
21159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
21163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2117bd6565f1Sksagiyam }
2118bd6565f1Sksagiyam 
2119021affd3Sksagiyam /*@
2120a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
2121021affd3Sksagiyam 
212220f4b53cSBarry Smith   Collective
2123021affd3Sksagiyam 
2124021affd3Sksagiyam   Input Parameters:
2125a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
2126a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
21270318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL`
2128021affd3Sksagiyam 
2129021affd3Sksagiyam   Level: advanced
2130021affd3Sksagiyam 
2131021affd3Sksagiyam   Notes:
2132420bcc1bSBarry Smith   This function is a wrapper around `PetscSectionView()`; in addition to the raw section, it saves information that associates the section points to the topology (`dm`) points. When the topology (`dm`) and the section are later loaded with `DMPlexTopologyLoad()` and `DMPlexSectionLoad()`, respectively, this information is used to match section points with topology points.
2133021affd3Sksagiyam 
21340318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2135021affd3Sksagiyam 
21361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
2137021affd3Sksagiyam @*/
2138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
2139d71ae5a4SJacob Faibussowitsch {
2140021affd3Sksagiyam   PetscBool ishdf5;
2141021affd3Sksagiyam 
2142021affd3Sksagiyam   PetscFunctionBegin;
2143021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2144021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21450318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2146021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21489566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
2149021affd3Sksagiyam   if (ishdf5) {
2150021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
21519566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
2152021affd3Sksagiyam #else
2153021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2154021affd3Sksagiyam #endif
2155021affd3Sksagiyam   }
21569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
21573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2158021affd3Sksagiyam }
2159021affd3Sksagiyam 
21603e97647fSksagiyam /*@
21613e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
21623e97647fSksagiyam 
216320f4b53cSBarry Smith   Collective
21643e97647fSksagiyam 
21653e97647fSksagiyam   Input Parameters:
2166a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2167a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
21680318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
21693e97647fSksagiyam - vec       - The global vector to be saved
21703e97647fSksagiyam 
21713e97647fSksagiyam   Level: advanced
21723e97647fSksagiyam 
21733e97647fSksagiyam   Notes:
21740318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
21753e97647fSksagiyam 
217660225df5SJacob Faibussowitsch   Calling sequence:
2177a1cb98faSBarry Smith .vb
2178a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2179a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2180a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2181a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2182a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2183a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2184a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2185a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2186a1cb98faSBarry Smith        PetscSectionSetUp(section);
2187a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2188a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2189a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2190a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2191a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2192a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2193a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2194a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2195a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2196a1cb98faSBarry Smith        DMDestroy(&dm);
2197a1cb98faSBarry Smith .ve
21983e97647fSksagiyam 
21991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22003e97647fSksagiyam @*/
2201d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2202d71ae5a4SJacob Faibussowitsch {
22033e97647fSksagiyam   PetscBool ishdf5;
22043e97647fSksagiyam 
22053e97647fSksagiyam   PetscFunctionBegin;
22063e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22073e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22080318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22093e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22103e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22113e97647fSksagiyam   /* Check consistency */
22123e97647fSksagiyam   {
22133e97647fSksagiyam     PetscSection section;
22143e97647fSksagiyam     PetscBool    includesConstraints;
22153e97647fSksagiyam     PetscInt     m, m1;
22163e97647fSksagiyam 
22179566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22189566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
22199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22209566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22219566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
222263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
22233e97647fSksagiyam   }
22249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22263e97647fSksagiyam   if (ishdf5) {
22273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22289566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22293e97647fSksagiyam #else
22303e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22313e97647fSksagiyam #endif
22323e97647fSksagiyam   }
22339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22353e97647fSksagiyam }
22363e97647fSksagiyam 
22373e97647fSksagiyam /*@
22383e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
22393e97647fSksagiyam 
224020f4b53cSBarry Smith   Collective
22413e97647fSksagiyam 
22423e97647fSksagiyam   Input Parameters:
2243a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2244a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
22450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL`
22463e97647fSksagiyam - vec       - The local vector to be saved
22473e97647fSksagiyam 
22483e97647fSksagiyam   Level: advanced
22493e97647fSksagiyam 
2250a1cb98faSBarry Smith   Note:
22510318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
22523e97647fSksagiyam 
225360225df5SJacob Faibussowitsch   Calling sequence:
2254a1cb98faSBarry Smith .vb
2255a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2256a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2257a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2258a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2259a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2260a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2261a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2262a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2263a1cb98faSBarry Smith        PetscSectionSetUp(section);
2264a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2265a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2266a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2267a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2268a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2269a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2270a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2271a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2272a1cb98faSBarry Smith        DMDestroy(&dm);
2273a1cb98faSBarry Smith .ve
22743e97647fSksagiyam 
22751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22763e97647fSksagiyam @*/
2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2278d71ae5a4SJacob Faibussowitsch {
22793e97647fSksagiyam   PetscBool ishdf5;
22803e97647fSksagiyam 
22813e97647fSksagiyam   PetscFunctionBegin;
22823e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22833e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22840318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22853e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22863e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22873e97647fSksagiyam   /* Check consistency */
22883e97647fSksagiyam   {
22893e97647fSksagiyam     PetscSection section;
22903e97647fSksagiyam     PetscBool    includesConstraints;
22913e97647fSksagiyam     PetscInt     m, m1;
22923e97647fSksagiyam 
22939566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22949566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
22959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22969566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22979566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
229863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
22993e97647fSksagiyam   }
23009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23023e97647fSksagiyam   if (ishdf5) {
23033e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
23049566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
23053e97647fSksagiyam #else
23063e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23073e97647fSksagiyam #endif
23083e97647fSksagiyam   }
23099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23113e97647fSksagiyam }
23123e97647fSksagiyam 
2313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2314d71ae5a4SJacob Faibussowitsch {
2315d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
23162c40f234SMatthew G. Knepley 
23172c40f234SMatthew G. Knepley   PetscFunctionBegin;
23182c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23192c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2321d4f5a9a0SVaclav Hapla   if (ishdf5) {
23222c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
23239c48423bSVaclav Hapla     PetscViewerFormat format;
23249566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23259c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
23269566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2327509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23289566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
232998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23312c40f234SMatthew G. Knepley #else
23322c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2333552f7358SJed Brown #endif
233498921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2335552f7358SJed Brown }
2336552f7358SJed Brown 
2337ea8e1828Sksagiyam /*@
2338a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2339ea8e1828Sksagiyam 
234020f4b53cSBarry Smith   Collective
2341ea8e1828Sksagiyam 
2342ea8e1828Sksagiyam   Input Parameters:
2343a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2344a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2345ea8e1828Sksagiyam 
23462fe279fdSBarry Smith   Output Parameter:
234720f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded
2348dec9e869Sksagiyam 
2349ea8e1828Sksagiyam   Level: advanced
2350ea8e1828Sksagiyam 
23511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2352a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2353ea8e1828Sksagiyam @*/
2354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2355d71ae5a4SJacob Faibussowitsch {
2356ea8e1828Sksagiyam   PetscBool ishdf5;
2357ea8e1828Sksagiyam 
2358ea8e1828Sksagiyam   PetscFunctionBegin;
2359ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2360ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23614f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
23629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2364ea8e1828Sksagiyam   if (ishdf5) {
2365ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2366ea8e1828Sksagiyam     PetscViewerFormat format;
23679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2368ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23699566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
237098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2371ea8e1828Sksagiyam #else
2372ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2373ea8e1828Sksagiyam #endif
2374ea8e1828Sksagiyam   }
23759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
23763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2377ea8e1828Sksagiyam }
2378ea8e1828Sksagiyam 
23793e701f1cSksagiyam /*@
2380a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
23813e701f1cSksagiyam 
238220f4b53cSBarry Smith   Collective
23833e701f1cSksagiyam 
23843e701f1cSksagiyam   Input Parameters:
2385a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2386a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2387a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
23883e701f1cSksagiyam 
23893e701f1cSksagiyam   Level: advanced
23903e701f1cSksagiyam 
23911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2392a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23933e701f1cSksagiyam @*/
2394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2395d71ae5a4SJacob Faibussowitsch {
23963e701f1cSksagiyam   PetscBool ishdf5;
23973e701f1cSksagiyam 
23983e701f1cSksagiyam   PetscFunctionBegin;
23993e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24003e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2401c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24043e701f1cSksagiyam   if (ishdf5) {
24053e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
24063e701f1cSksagiyam     PetscViewerFormat format;
24079566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
24083e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24099566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
241098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
24113e701f1cSksagiyam #else
24123e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24133e701f1cSksagiyam #endif
24143e701f1cSksagiyam   }
24159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24173e701f1cSksagiyam }
24183e701f1cSksagiyam 
2419b08ad5deSksagiyam /*@
2420a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2421b08ad5deSksagiyam 
242220f4b53cSBarry Smith   Collective
2423b08ad5deSksagiyam 
2424b08ad5deSksagiyam   Input Parameters:
2425a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2426a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
242720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2428b08ad5deSksagiyam 
2429b08ad5deSksagiyam   Level: advanced
2430b08ad5deSksagiyam 
2431a1cb98faSBarry Smith   Note:
2432a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2433e6368b79SVaclav Hapla 
24341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2435a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2436b08ad5deSksagiyam @*/
2437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2438d71ae5a4SJacob Faibussowitsch {
2439b08ad5deSksagiyam   PetscBool ishdf5;
2440b08ad5deSksagiyam 
2441b08ad5deSksagiyam   PetscFunctionBegin;
2442b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2443b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2444e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2447b08ad5deSksagiyam   if (ishdf5) {
2448b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2449b08ad5deSksagiyam     PetscViewerFormat format;
2450b08ad5deSksagiyam 
24519566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2452b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24539566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
245498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2455b08ad5deSksagiyam #else
2456b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2457b08ad5deSksagiyam #endif
2458b08ad5deSksagiyam   }
24599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2461b08ad5deSksagiyam }
2462b08ad5deSksagiyam 
2463f84dd6b4Sksagiyam /*@
2464a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2465f84dd6b4Sksagiyam 
246620f4b53cSBarry Smith   Collective
2467f84dd6b4Sksagiyam 
2468f84dd6b4Sksagiyam   Input Parameters:
2469a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2470a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
24710318f8a0SStefano Zampini . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL`
2472a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2473f84dd6b4Sksagiyam 
2474a4e35b19SJacob Faibussowitsch   Output Parameters:
247520f4b53cSBarry Smith + globalDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a global `Vec` associated with the `sectiondm`'s global section (`NULL` if not needed)
247620f4b53cSBarry Smith - localDofSF  - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a local `Vec` associated with the `sectiondm`'s local section (`NULL` if not needed)
2477f84dd6b4Sksagiyam 
2478f84dd6b4Sksagiyam   Level: advanced
2479f84dd6b4Sksagiyam 
2480f84dd6b4Sksagiyam   Notes:
248120f4b53cSBarry Smith   This function is a wrapper around `PetscSectionLoad()`; it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in `dm`. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points.
2482f84dd6b4Sksagiyam 
24830318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2484f84dd6b4Sksagiyam 
248520f4b53cSBarry Smith   The output parameter, `globalDofSF` (`localDofSF`), can later be used with `DMPlexGlobalVectorLoad()` (`DMPlexLocalVectorLoad()`) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section.
2486f84dd6b4Sksagiyam 
2487f84dd6b4Sksagiyam   Example using 2 processes:
2488a1cb98faSBarry Smith .vb
2489a1cb98faSBarry Smith   NX (number of points on dm): 4
2490a1cb98faSBarry Smith   sectionA                   : the on-disk section
2491a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2492a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2493a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2494a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2495f84dd6b4Sksagiyam 
2496a1cb98faSBarry Smith                                      rank 0    rank 1
2497a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2498a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2499a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2500a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2501a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2502a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2503a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2504a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2505a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2506a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2507a1cb98faSBarry Smith .ve
2508a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2509a1cb98faSBarry Smith 
25101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2511f84dd6b4Sksagiyam @*/
2512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2513d71ae5a4SJacob Faibussowitsch {
2514f84dd6b4Sksagiyam   PetscBool ishdf5;
2515f84dd6b4Sksagiyam 
2516f84dd6b4Sksagiyam   PetscFunctionBegin;
2517f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2518f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25190318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2520f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2521f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
25224f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
25234f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
25249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2526f84dd6b4Sksagiyam   if (ishdf5) {
2527f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
25289566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2529f84dd6b4Sksagiyam #else
2530f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2531f84dd6b4Sksagiyam #endif
2532f84dd6b4Sksagiyam   }
25339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
25343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2535f84dd6b4Sksagiyam }
2536f84dd6b4Sksagiyam 
25378be3dfe1Sksagiyam /*@
25388be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
25398be3dfe1Sksagiyam 
254020f4b53cSBarry Smith   Collective
25418be3dfe1Sksagiyam 
25428be3dfe1Sksagiyam   Input Parameters:
2543a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2544a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
25450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
2546a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
25478be3dfe1Sksagiyam - vec       - The global vector to set values of
25488be3dfe1Sksagiyam 
25498be3dfe1Sksagiyam   Level: advanced
25508be3dfe1Sksagiyam 
25518be3dfe1Sksagiyam   Notes:
25520318f8a0SStefano Zampini   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
25538be3dfe1Sksagiyam 
255460225df5SJacob Faibussowitsch   Calling sequence:
2555a1cb98faSBarry Smith .vb
2556a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2557a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2558a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2559a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2560a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2561a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2562a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2563a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2564a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2565a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2566a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2567a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2568a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2569a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2570a1cb98faSBarry Smith        DMDestroy(&dm);
2571a1cb98faSBarry Smith .ve
25728be3dfe1Sksagiyam 
25731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2574a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
25758be3dfe1Sksagiyam @*/
2576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2577d71ae5a4SJacob Faibussowitsch {
25788be3dfe1Sksagiyam   PetscBool ishdf5;
25798be3dfe1Sksagiyam 
25808be3dfe1Sksagiyam   PetscFunctionBegin;
25818be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25828be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25830318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
25848be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
25858be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
25868be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
25878be3dfe1Sksagiyam   /* Check consistency */
25888be3dfe1Sksagiyam   {
25898be3dfe1Sksagiyam     PetscSection section;
25908be3dfe1Sksagiyam     PetscBool    includesConstraints;
25918be3dfe1Sksagiyam     PetscInt     m, m1;
25928be3dfe1Sksagiyam 
25939566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25949566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
25959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25969566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25979566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
259863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
25998be3dfe1Sksagiyam   }
26009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26019566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26028be3dfe1Sksagiyam   if (ishdf5) {
26038be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26049566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26058be3dfe1Sksagiyam #else
26068be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26078be3dfe1Sksagiyam #endif
26088be3dfe1Sksagiyam   }
26099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26118be3dfe1Sksagiyam }
26128be3dfe1Sksagiyam 
26138be3dfe1Sksagiyam /*@
26148be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
26158be3dfe1Sksagiyam 
261620f4b53cSBarry Smith   Collective
26178be3dfe1Sksagiyam 
26188be3dfe1Sksagiyam   Input Parameters:
2619a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2620a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
26210318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL`
2622a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
26238be3dfe1Sksagiyam - vec       - The local vector to set values of
26248be3dfe1Sksagiyam 
26258be3dfe1Sksagiyam   Level: advanced
26268be3dfe1Sksagiyam 
26278be3dfe1Sksagiyam   Notes:
26280318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
26298be3dfe1Sksagiyam 
263060225df5SJacob Faibussowitsch   Calling sequence:
2631a1cb98faSBarry Smith .vb
2632a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2633a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2634a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2635a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2636a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2637a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2638a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2639a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2640a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2641a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2642a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2643a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2644a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2645a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2646a1cb98faSBarry Smith        DMDestroy(&dm);
2647a1cb98faSBarry Smith .ve
26488be3dfe1Sksagiyam 
26491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2650a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
26518be3dfe1Sksagiyam @*/
2652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2653d71ae5a4SJacob Faibussowitsch {
26548be3dfe1Sksagiyam   PetscBool ishdf5;
26558be3dfe1Sksagiyam 
26568be3dfe1Sksagiyam   PetscFunctionBegin;
26578be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26588be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26590318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
26608be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
26618be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
26628be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
26638be3dfe1Sksagiyam   /* Check consistency */
26648be3dfe1Sksagiyam   {
26658be3dfe1Sksagiyam     PetscSection section;
26668be3dfe1Sksagiyam     PetscBool    includesConstraints;
26678be3dfe1Sksagiyam     PetscInt     m, m1;
26688be3dfe1Sksagiyam 
26699566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
26709566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
26719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
26729566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
26739566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
267463a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
26758be3dfe1Sksagiyam   }
26769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26788be3dfe1Sksagiyam   if (ishdf5) {
26798be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26809566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26818be3dfe1Sksagiyam #else
26828be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26838be3dfe1Sksagiyam #endif
26848be3dfe1Sksagiyam   }
26859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26878be3dfe1Sksagiyam }
26888be3dfe1Sksagiyam 
2689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2690d71ae5a4SJacob Faibussowitsch {
2691552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2692552f7358SJed Brown 
2693552f7358SJed Brown   PetscFunctionBegin;
26949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
26969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
26986c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL));
26992e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
27002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
27012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
27022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
27036bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
27046bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2705adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL));
2706adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL));
2707adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL));
2708adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL));
2709c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2710c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
2711d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL));
2712d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL));
27135f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
27143ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
27159566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
27169566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
27179566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
27189566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
27199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
27209566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
272121027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27229f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
27239566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
27249566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
27259566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
27261d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
27279566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
27289566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
27299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
27309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
27319566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
27324e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
27336725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
27346725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
27359566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
27369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
27379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
27389566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
27399566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
27409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
27419566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
27429566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
27439566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
27449566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
27459566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2746552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
27479566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
27483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2749552f7358SJed Brown }
2750552f7358SJed Brown 
2751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2752d71ae5a4SJacob Faibussowitsch {
2753d02c7345SMatthew G. Knepley   PetscSection           sectionGlobal, sectionLocal;
2754acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
27559fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2756837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2757b412c318SBarry Smith   MatType                mtype;
27581428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2759552f7358SJed Brown 
2760552f7358SJed Brown   PetscFunctionBegin;
27619566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2762b412c318SBarry Smith   mtype = dm->mattype;
2763d02c7345SMatthew G. Knepley   PetscCall(DMGetLocalSection(dm, &sectionLocal));
27649566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
27659566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
27669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
27679fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
27689566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
27699566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
27709566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
27719566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
27729566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2773acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
27749566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
27759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
27769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
27779566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
27789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
27799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
27809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
27819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2782552f7358SJed Brown   if (!isShell) {
2783837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
27849fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2785863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2786552f7358SJed Brown 
27879566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
27889fca9976SJed Brown 
27899fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
27909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2791863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2792e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2793863027abSJed Brown       switch (dm->blocking_type) {
27940e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
27959fca9976SJed Brown         PetscInt bdof, offset;
2796a9d99c84SMatthew G. Knepley 
27979566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
27989fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
27999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
2800d02c7345SMatthew G. Knepley         for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof;
2801d02c7345SMatthew G. Knepley         // Signal block concatenation
2802d02c7345SMatthew G. Knepley         if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof);
28031d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
28041d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
28051d17a0a3SMatthew G. Knepley         if (dof) {
28069371c9d4SSatish Balay           if (bs < 0) {
28079371c9d4SSatish Balay             bs = bdof;
28089371c9d4SSatish Balay           } else if (bs != bdof) {
28099371c9d4SSatish Balay             bs = 1;
28109371c9d4SSatish Balay           }
2811552f7358SJed Brown         }
2812863027abSJed Brown       } break;
2813863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2814863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2815863027abSJed Brown           PetscInt num_comp, bdof, offset;
2816863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2817863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2818863027abSJed Brown           if (dof < 0) continue;
2819863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2820863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2821863027abSJed Brown           PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp);
2822863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2823863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2824863027abSJed Brown           // Handle possibly constant block size (unlikely)
2825863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2826863027abSJed Brown           if (dof) {
2827863027abSJed Brown             if (bs < 0) {
2828863027abSJed Brown               bs = bdof;
2829863027abSJed Brown             } else if (bs != bdof) {
2830863027abSJed Brown               bs = 1;
2831863027abSJed Brown             }
2832863027abSJed Brown           }
2833863027abSJed Brown         }
2834863027abSJed Brown       } break;
2835863027abSJed Brown       }
28362a28c762SMatthew G Knepley     }
28372a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2838e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2839e432b41dSStefano Zampini     bsLocal[1] = bs;
28409566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2841e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2842e432b41dSStefano Zampini     else bs = bsMinMax[0];
28436fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
28449566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
28450682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
28469566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
28479566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
28480682b8bbSJed Brown     } else {
28499566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
28509566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
28519566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2852552f7358SJed Brown     }
28539fca9976SJed Brown     { // Consolidate blocks
28549fca9976SJed Brown       PetscInt nblocks = 0;
28559fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
28569fca9976SJed Brown         if (pblocks[i] == 0) continue;
2857d02c7345SMatthew G. Knepley         // Negative block size indicates the blocks should be concatenated
2858d02c7345SMatthew G. Knepley         if (pblocks[i] < 0) {
2859d02c7345SMatthew G. Knepley           pblocks[i] = -pblocks[i];
2860d02c7345SMatthew G. Knepley           pblocks[nblocks - 1] += pblocks[i];
2861d02c7345SMatthew G. Knepley         } else {
28629fca9976SJed Brown           pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2863d02c7345SMatthew G. Knepley         }
2864ad540459SPierre Jolivet         for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]);
28659fca9976SJed Brown       }
28669fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
28679fca9976SJed Brown     }
28689fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2869aa0f6e3cSJed Brown   }
28709566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
28713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2872552f7358SJed Brown }
2873552f7358SJed Brown 
28747cd05799SMatthew G. Knepley /*@
2875a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2876be36d101SStefano Zampini 
2877a1cb98faSBarry Smith   Not Collective
2878be36d101SStefano Zampini 
2879be36d101SStefano Zampini   Input Parameter:
288060225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2881be36d101SStefano Zampini 
28822fe279fdSBarry Smith   Output Parameter:
2883be36d101SStefano Zampini . subsection - The subdomain section
2884be36d101SStefano Zampini 
2885be36d101SStefano Zampini   Level: developer
2886be36d101SStefano Zampini 
28871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
28887cd05799SMatthew G. Knepley @*/
2889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2890d71ae5a4SJacob Faibussowitsch {
2891be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2892be36d101SStefano Zampini 
2893be36d101SStefano Zampini   PetscFunctionBegin;
2894be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2895be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2896be36d101SStefano Zampini     PetscSection section;
2897be36d101SStefano Zampini     PetscSF      sf;
2898be36d101SStefano Zampini 
28999566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
29009566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
2901eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
29029566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2903be36d101SStefano Zampini   }
2904be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
29053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2906be36d101SStefano Zampini }
2907be36d101SStefano Zampini 
2908552f7358SJed Brown /*@
290920f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2910552f7358SJed Brown 
2911a1cb98faSBarry Smith   Not Collective
2912552f7358SJed Brown 
2913552f7358SJed Brown   Input Parameter:
291460225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2915552f7358SJed Brown 
2916552f7358SJed Brown   Output Parameters:
2917552f7358SJed Brown + pStart - The first mesh point
2918552f7358SJed Brown - pEnd   - The upper bound for mesh points
2919552f7358SJed Brown 
2920552f7358SJed Brown   Level: beginner
2921552f7358SJed Brown 
29221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2923552f7358SJed Brown @*/
2924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2925d71ae5a4SJacob Faibussowitsch {
2926552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2927552f7358SJed Brown 
2928552f7358SJed Brown   PetscFunctionBegin;
2929552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29309f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
29319f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
29323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2933552f7358SJed Brown }
2934552f7358SJed Brown 
2935552f7358SJed Brown /*@
293620f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2937552f7358SJed Brown 
2938a1cb98faSBarry Smith   Not Collective
2939552f7358SJed Brown 
2940552f7358SJed Brown   Input Parameters:
294160225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2942552f7358SJed Brown . pStart - The first mesh point
2943552f7358SJed Brown - pEnd   - The upper bound for mesh points
2944552f7358SJed Brown 
2945552f7358SJed Brown   Level: beginner
2946552f7358SJed Brown 
29471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2948552f7358SJed Brown @*/
2949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2950d71ae5a4SJacob Faibussowitsch {
2951552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2952552f7358SJed Brown 
2953552f7358SJed Brown   PetscFunctionBegin;
2954552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
29569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
295721027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
29583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2959552f7358SJed Brown }
2960552f7358SJed Brown 
2961552f7358SJed Brown /*@
2962eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2963552f7358SJed Brown 
2964a1cb98faSBarry Smith   Not Collective
2965552f7358SJed Brown 
2966552f7358SJed Brown   Input Parameters:
296760225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2968a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2969552f7358SJed Brown 
2970552f7358SJed Brown   Output Parameter:
297120f4b53cSBarry Smith . size - The cone size for point `p`
2972552f7358SJed Brown 
2973552f7358SJed Brown   Level: beginner
2974552f7358SJed Brown 
29751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2976552f7358SJed Brown @*/
2977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2978d71ae5a4SJacob Faibussowitsch {
2979552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2980552f7358SJed Brown 
2981552f7358SJed Brown   PetscFunctionBegin;
2982552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29834f572ea9SToby Isaac   PetscAssertPointer(size, 3);
29849f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
29859f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
29863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2987552f7358SJed Brown }
2988552f7358SJed Brown 
2989552f7358SJed Brown /*@
2990eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2991552f7358SJed Brown 
2992a1cb98faSBarry Smith   Not Collective
2993552f7358SJed Brown 
2994552f7358SJed Brown   Input Parameters:
299560225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
2996a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
299720f4b53cSBarry Smith - size - The cone size for point `p`
2998552f7358SJed Brown 
2999552f7358SJed Brown   Level: beginner
3000552f7358SJed Brown 
3001a1cb98faSBarry Smith   Note:
3002a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
3003a1cb98faSBarry Smith 
30041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
3005552f7358SJed Brown @*/
3006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
3007d71ae5a4SJacob Faibussowitsch {
3008552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3009552f7358SJed Brown 
3010552f7358SJed Brown   PetscFunctionBegin;
3011552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30129f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
30139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
30143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3015552f7358SJed Brown }
3016552f7358SJed Brown 
3017552f7358SJed Brown /*@C
3018eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
3019552f7358SJed Brown 
3020a1cb98faSBarry Smith   Not Collective
3021552f7358SJed Brown 
3022552f7358SJed Brown   Input Parameters:
3023a1cb98faSBarry Smith + dm - The `DMPLEX`
3024a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3025552f7358SJed Brown 
3026552f7358SJed Brown   Output Parameter:
302720f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
3028552f7358SJed Brown 
3029552f7358SJed Brown   Level: beginner
3030552f7358SJed Brown 
303160225df5SJacob Faibussowitsch   Fortran Notes:
3032a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
3033a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
30343813dfbdSMatthew G Knepley 
30351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
3036552f7358SJed Brown @*/
3037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
3038d71ae5a4SJacob Faibussowitsch {
3039552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3040552f7358SJed Brown   PetscInt off;
3041552f7358SJed Brown 
3042552f7358SJed Brown   PetscFunctionBegin;
3043552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30444f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
30459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30468e3a54c0SPierre Jolivet   *cone = PetscSafePointerPlusOffset(mesh->cones, off);
30473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3048552f7358SJed Brown }
3049552f7358SJed Brown 
30500ce7577fSVaclav Hapla /*@C
30510ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
30520ce7577fSVaclav Hapla 
3053a1cb98faSBarry Smith   Not Collective
30540ce7577fSVaclav Hapla 
30550ce7577fSVaclav Hapla   Input Parameters:
3056a1cb98faSBarry Smith + dm - The `DMPLEX`
3057a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
30580ce7577fSVaclav Hapla 
3059d8d19677SJose E. Roman   Output Parameters:
306020f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
306120f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
30620ce7577fSVaclav Hapla 
30630ce7577fSVaclav Hapla   Level: intermediate
30640ce7577fSVaclav Hapla 
30651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
30660ce7577fSVaclav Hapla @*/
3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
3068d71ae5a4SJacob Faibussowitsch {
30690ce7577fSVaclav Hapla   PetscSection cs, newcs;
30700ce7577fSVaclav Hapla   PetscInt    *cones;
30710ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
30720ce7577fSVaclav Hapla   PetscInt     n;
30730ce7577fSVaclav Hapla 
30740ce7577fSVaclav Hapla   PetscFunctionBegin;
30759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
30769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
30779566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
30780ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
30790ce7577fSVaclav Hapla   if (pCones) {
30809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
30819566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
30820ce7577fSVaclav Hapla   }
30833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30840ce7577fSVaclav Hapla }
30850ce7577fSVaclav Hapla 
3086af9eab45SVaclav Hapla /*@
3087af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
3088d4636a37SVaclav Hapla 
3089a1cb98faSBarry Smith   Not Collective
3090d4636a37SVaclav Hapla 
3091d4636a37SVaclav Hapla   Input Parameters:
3092a1cb98faSBarry Smith + dm     - The `DMPLEX`
3093a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3094d4636a37SVaclav Hapla 
3095d4636a37SVaclav Hapla   Output Parameter:
3096af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
3097d4636a37SVaclav Hapla 
3098d4636a37SVaclav Hapla   Level: advanced
3099d4636a37SVaclav Hapla 
3100af9eab45SVaclav Hapla   Notes:
310120f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
3102af9eab45SVaclav Hapla 
3103a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
3104a1cb98faSBarry Smith 
31051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
3106a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
3107d4636a37SVaclav Hapla @*/
3108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
3109d71ae5a4SJacob Faibussowitsch {
3110af9eab45SVaclav Hapla   IS      *expandedPointsAll;
3111af9eab45SVaclav Hapla   PetscInt depth;
3112d4636a37SVaclav Hapla 
3113d4636a37SVaclav Hapla   PetscFunctionBegin;
3114af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3115af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31164f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
31179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
3118af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
31199566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
31209566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
31213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3122af9eab45SVaclav Hapla }
3123af9eab45SVaclav Hapla 
3124af9eab45SVaclav Hapla /*@
3125af9eab45SVaclav Hapla   DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones).
3126af9eab45SVaclav Hapla 
3127a1cb98faSBarry Smith   Not Collective
3128af9eab45SVaclav Hapla 
3129af9eab45SVaclav Hapla   Input Parameters:
3130a1cb98faSBarry Smith + dm     - The `DMPLEX`
3131a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3132af9eab45SVaclav Hapla 
3133d8d19677SJose E. Roman   Output Parameters:
3134a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3135af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
3136af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3137af9eab45SVaclav Hapla 
3138af9eab45SVaclav Hapla   Level: advanced
3139af9eab45SVaclav Hapla 
3140af9eab45SVaclav Hapla   Notes:
3141a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
3142af9eab45SVaclav Hapla 
3143a4e35b19SJacob Faibussowitsch   Array `expandedPoints` has size equal to `depth`. Each `expandedPoints`[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points.
3144af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
3145af9eab45SVaclav Hapla 
3146a4e35b19SJacob Faibussowitsch   Array section has size equal to `depth`.  Each `PetscSection` `sections`[d] realizes mapping from `expandedPoints`[d+1] (section points) to `expandedPoints`[d] (section dofs) as follows\:
3147a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
3148a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
3149af9eab45SVaclav Hapla 
31501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3151a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
3152af9eab45SVaclav Hapla @*/
3153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3154d71ae5a4SJacob Faibussowitsch {
3155af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
3156af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
3157af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
3158af9eab45SVaclav Hapla   IS             *expandedPoints_;
3159af9eab45SVaclav Hapla   PetscSection   *sections_;
3160af9eab45SVaclav Hapla 
3161af9eab45SVaclav Hapla   PetscFunctionBegin;
3162af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3163af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31644f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
31654f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
31664f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
31679566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
31689566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
31699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
31709566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
31719566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
3172af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
3173af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
31749566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
31759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
3176af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
3178af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
31799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
31809566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3181af9eab45SVaclav Hapla       } else {
31829566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3183af9eab45SVaclav Hapla       }
3184af9eab45SVaclav Hapla     }
31859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
31869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
31879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3188af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
31909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3191af9eab45SVaclav Hapla       if (cn > 1) {
31929566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
31939566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3194af9eab45SVaclav Hapla       } else {
3195af9eab45SVaclav Hapla         newarr[co] = arr[i];
3196af9eab45SVaclav Hapla       }
3197af9eab45SVaclav Hapla     }
31989566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3199af9eab45SVaclav Hapla     arr = newarr;
3200af9eab45SVaclav Hapla     n   = newn;
3201af9eab45SVaclav Hapla   }
32029566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3203af9eab45SVaclav Hapla   *depth = depth_;
3204af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3205af9eab45SVaclav Hapla   else {
32069566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
32079566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3208af9eab45SVaclav Hapla   }
3209af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3210af9eab45SVaclav Hapla   else {
32119566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
32129566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3213af9eab45SVaclav Hapla   }
32143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3215af9eab45SVaclav Hapla }
3216af9eab45SVaclav Hapla 
3217af9eab45SVaclav Hapla /*@
3218a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3219af9eab45SVaclav Hapla 
3220a1cb98faSBarry Smith   Not Collective
3221af9eab45SVaclav Hapla 
3222af9eab45SVaclav Hapla   Input Parameters:
3223a1cb98faSBarry Smith + dm     - The `DMPLEX`
3224a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3225af9eab45SVaclav Hapla 
3226d8d19677SJose E. Roman   Output Parameters:
3227a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3228af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3229af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3230af9eab45SVaclav Hapla 
3231af9eab45SVaclav Hapla   Level: advanced
3232af9eab45SVaclav Hapla 
3233a1cb98faSBarry Smith   Note:
3234a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3235af9eab45SVaclav Hapla 
32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3237a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3238af9eab45SVaclav Hapla @*/
3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3240d71ae5a4SJacob Faibussowitsch {
3241af9eab45SVaclav Hapla   PetscInt d, depth_;
3242af9eab45SVaclav Hapla 
3243af9eab45SVaclav Hapla   PetscFunctionBegin;
32449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
32451dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3246af9eab45SVaclav Hapla   if (depth) *depth = 0;
3247af9eab45SVaclav Hapla   if (expandedPoints) {
32489566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
32499566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3250af9eab45SVaclav Hapla   }
3251af9eab45SVaclav Hapla   if (sections) {
32529566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
32539566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3254af9eab45SVaclav Hapla   }
32553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3256d4636a37SVaclav Hapla }
3257d4636a37SVaclav Hapla 
3258552f7358SJed Brown /*@
325992371b87SBarry Smith   DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point
3260552f7358SJed Brown 
3261a1cb98faSBarry Smith   Not Collective
3262552f7358SJed Brown 
3263552f7358SJed Brown   Input Parameters:
326460225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3265a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
326620f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3267552f7358SJed Brown 
3268552f7358SJed Brown   Level: beginner
3269552f7358SJed Brown 
3270a1cb98faSBarry Smith   Note:
3271a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3272a1cb98faSBarry Smith 
32731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3274552f7358SJed Brown @*/
3275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3276d71ae5a4SJacob Faibussowitsch {
3277552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3278552f7358SJed Brown   PetscInt dof, off, c;
3279552f7358SJed Brown 
3280552f7358SJed Brown   PetscFunctionBegin;
3281552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32834f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
32849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3285db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3286db485b19SStefano Zampini     PetscInt pStart, pEnd;
3287db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
328863a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3289552f7358SJed Brown     for (c = 0; c < dof; ++c) {
329063a3b9bcSJacob Faibussowitsch       PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd);
3291552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3292552f7358SJed Brown     }
3293db485b19SStefano Zampini   } else {
3294db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3295db485b19SStefano Zampini   }
32963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3297552f7358SJed Brown }
3298552f7358SJed Brown 
3299552f7358SJed Brown /*@C
3300eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3301552f7358SJed Brown 
3302a1cb98faSBarry Smith   Not Collective
3303552f7358SJed Brown 
3304552f7358SJed Brown   Input Parameters:
330560225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3306a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3307552f7358SJed Brown 
3308552f7358SJed Brown   Output Parameter:
330920f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3310b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3311552f7358SJed Brown 
3312552f7358SJed Brown   Level: beginner
3313552f7358SJed Brown 
3314a1cb98faSBarry Smith   Note:
3315b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3316b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3317a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3318b5a892a1SMatthew G. Knepley   with the identity.
3319b5a892a1SMatthew G. Knepley 
332060225df5SJacob Faibussowitsch   Fortran Notes:
3321a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3322a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
33233813dfbdSMatthew G Knepley 
33241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3325552f7358SJed Brown @*/
3326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3327d71ae5a4SJacob Faibussowitsch {
3328552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3329552f7358SJed Brown   PetscInt off;
3330552f7358SJed Brown 
3331552f7358SJed Brown   PetscFunctionBegin;
3332552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3334552f7358SJed Brown     PetscInt dof;
33359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33364f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3337552f7358SJed Brown   }
33389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33390d644c17SKarl Rupp 
3340552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
33413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3342552f7358SJed Brown }
3343552f7358SJed Brown 
3344552f7358SJed Brown /*@
3345eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3346552f7358SJed Brown 
3347a1cb98faSBarry Smith   Not Collective
3348552f7358SJed Brown 
3349552f7358SJed Brown   Input Parameters:
335060225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3351a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3352b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3353b5a892a1SMatthew G. Knepley 
3354552f7358SJed Brown   Level: beginner
3355552f7358SJed Brown 
3356a1cb98faSBarry Smith   Notes:
3357a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3358a1cb98faSBarry Smith 
3359a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3360a1cb98faSBarry Smith 
33611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3362552f7358SJed Brown @*/
3363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3364d71ae5a4SJacob Faibussowitsch {
3365552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3366552f7358SJed Brown   PetscInt pStart, pEnd;
3367552f7358SJed Brown   PetscInt dof, off, c;
3368552f7358SJed Brown 
3369552f7358SJed Brown   PetscFunctionBegin;
3370552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33724f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
33739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3374db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3375db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
337663a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3377552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3378552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3379552f7358SJed Brown 
33809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
33811dca8a05SBarry Smith       PetscCheck(!o || (o >= -(cdof + 1) && o < cdof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof + 1), cdof);
3382552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3383552f7358SJed Brown     }
3384db485b19SStefano Zampini   } else {
3385db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3386db485b19SStefano Zampini   }
33873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3388552f7358SJed Brown }
3389552f7358SJed Brown 
33907cd05799SMatthew G. Knepley /*@
3391eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
33927cd05799SMatthew G. Knepley 
3393a1cb98faSBarry Smith   Not Collective
33947cd05799SMatthew G. Knepley 
33957cd05799SMatthew G. Knepley   Input Parameters:
339660225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3397a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
33987cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
33997cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
34007cd05799SMatthew G. Knepley 
34017cd05799SMatthew G. Knepley   Level: beginner
34027cd05799SMatthew G. Knepley 
34031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34047cd05799SMatthew G. Knepley @*/
3405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3406d71ae5a4SJacob Faibussowitsch {
3407552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3408552f7358SJed Brown   PetscInt pStart, pEnd;
3409552f7358SJed Brown   PetscInt dof, off;
3410552f7358SJed Brown 
3411552f7358SJed Brown   PetscFunctionBegin;
3412552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3413a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
341563a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
341663a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd);
34179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
341863a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
3419a03d55ffSStefano Zampini   }
3420a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3421552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
34223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3423552f7358SJed Brown }
3424552f7358SJed Brown 
34257cd05799SMatthew G. Knepley /*@
3426eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
34277cd05799SMatthew G. Knepley 
3428a1cb98faSBarry Smith   Not Collective
34297cd05799SMatthew G. Knepley 
34307cd05799SMatthew G. Knepley   Input Parameters:
343160225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3432a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
34337cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
34347cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
34357cd05799SMatthew G. Knepley 
34367cd05799SMatthew G. Knepley   Level: beginner
34377cd05799SMatthew G. Knepley 
3438a1cb98faSBarry Smith   Note:
3439a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3440b5a892a1SMatthew G. Knepley 
34411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34427cd05799SMatthew G. Knepley @*/
3443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3444d71ae5a4SJacob Faibussowitsch {
344577c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
344677c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
344777c88f5bSMatthew G Knepley   PetscInt dof, off;
344877c88f5bSMatthew G Knepley 
344977c88f5bSMatthew G Knepley   PetscFunctionBegin;
345077c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3451a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
345363a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
34549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
345563a3b9bcSJacob Faibussowitsch     PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
3456a03d55ffSStefano Zampini   }
3457a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
345877c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
34593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346077c88f5bSMatthew G Knepley }
346177c88f5bSMatthew G Knepley 
34629f4ada15SMatthew G. Knepley /*@C
34639f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
34649f4ada15SMatthew G. Knepley 
34659f4ada15SMatthew G. Knepley   Not collective
34669f4ada15SMatthew G. Knepley 
34679f4ada15SMatthew G. Knepley   Input Parameters:
34689f4ada15SMatthew G. Knepley + dm - The DMPlex
34699f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
34709f4ada15SMatthew G. Knepley 
34719f4ada15SMatthew G. Knepley   Output Parameters:
347220f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
347320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34749f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34759f4ada15SMatthew G. Knepley 
34769f4ada15SMatthew G. Knepley   Level: beginner
34779f4ada15SMatthew G. Knepley 
34789f4ada15SMatthew G. Knepley   Notes:
34799f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34809f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
348120f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34829f4ada15SMatthew G. Knepley   with the identity.
34839f4ada15SMatthew G. Knepley 
34849f4ada15SMatthew G. Knepley   Fortran Notes:
348520f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
348620f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
34879f4ada15SMatthew G. Knepley 
34881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
34899f4ada15SMatthew G. Knepley @*/
34909f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
34919f4ada15SMatthew G. Knepley {
34929f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
34939f4ada15SMatthew G. Knepley 
34949f4ada15SMatthew G. Knepley   PetscFunctionBegin;
34959f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34969f4ada15SMatthew G. Knepley   if (mesh->tr) {
34979f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
34989f4ada15SMatthew G. Knepley   } else {
34999f4ada15SMatthew G. Knepley     PetscInt off;
35009f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
35019f4ada15SMatthew G. Knepley       PetscInt dof;
35029f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
35039f4ada15SMatthew G. Knepley       if (dof) {
35044f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
35054f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
35069f4ada15SMatthew G. Knepley       }
35079f4ada15SMatthew G. Knepley     }
35089f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
35098e3a54c0SPierre Jolivet     if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off);
35108e3a54c0SPierre Jolivet     if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off);
35119f4ada15SMatthew G. Knepley   }
35123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35139f4ada15SMatthew G. Knepley }
35149f4ada15SMatthew G. Knepley 
35159f4ada15SMatthew G. Knepley /*@C
35169f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
35179f4ada15SMatthew G. Knepley 
351820f4b53cSBarry Smith   Not Collective
35199f4ada15SMatthew G. Knepley 
35209f4ada15SMatthew G. Knepley   Input Parameters:
35219f4ada15SMatthew G. Knepley + dm   - The DMPlex
352220f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
35239f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
352420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
35259f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
35269f4ada15SMatthew G. Knepley 
35279f4ada15SMatthew G. Knepley   Level: beginner
35289f4ada15SMatthew G. Knepley 
35299f4ada15SMatthew G. Knepley   Notes:
35309f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
35319f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
353220f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
35339f4ada15SMatthew G. Knepley   with the identity.
35349f4ada15SMatthew G. Knepley 
353560225df5SJacob Faibussowitsch   Fortran Notes:
353620f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
353720f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
35389f4ada15SMatthew G. Knepley 
35391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
35409f4ada15SMatthew G. Knepley @*/
35419f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
35429f4ada15SMatthew G. Knepley {
35439f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
35449f4ada15SMatthew G. Knepley 
35459f4ada15SMatthew G. Knepley   PetscFunctionBegin;
35469f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35479f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
35483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35499f4ada15SMatthew G. Knepley }
35509f4ada15SMatthew G. Knepley 
3551552f7358SJed Brown /*@
3552eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3553552f7358SJed Brown 
3554a1cb98faSBarry Smith   Not Collective
3555552f7358SJed Brown 
3556552f7358SJed Brown   Input Parameters:
355760225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3558a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3559552f7358SJed Brown 
3560552f7358SJed Brown   Output Parameter:
356120f4b53cSBarry Smith . size - The support size for point `p`
3562552f7358SJed Brown 
3563552f7358SJed Brown   Level: beginner
3564552f7358SJed Brown 
35651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3566552f7358SJed Brown @*/
3567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3568d71ae5a4SJacob Faibussowitsch {
3569552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3570552f7358SJed Brown 
3571552f7358SJed Brown   PetscFunctionBegin;
3572552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35734f572ea9SToby Isaac   PetscAssertPointer(size, 3);
35749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
35753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3576552f7358SJed Brown }
3577552f7358SJed Brown 
3578552f7358SJed Brown /*@
3579eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3580552f7358SJed Brown 
3581a1cb98faSBarry Smith   Not Collective
3582552f7358SJed Brown 
3583552f7358SJed Brown   Input Parameters:
358460225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3585a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
358620f4b53cSBarry Smith - size - The support size for point `p`
3587552f7358SJed Brown 
3588a1cb98faSBarry Smith   Level: beginner
3589552f7358SJed Brown 
3590552f7358SJed Brown   Note:
359120f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3592552f7358SJed Brown 
35931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3594552f7358SJed Brown @*/
3595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3596d71ae5a4SJacob Faibussowitsch {
3597552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3598552f7358SJed Brown 
3599552f7358SJed Brown   PetscFunctionBegin;
3600552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
36023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3603552f7358SJed Brown }
3604552f7358SJed Brown 
3605552f7358SJed Brown /*@C
3606eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3607552f7358SJed Brown 
3608a1cb98faSBarry Smith   Not Collective
3609552f7358SJed Brown 
3610552f7358SJed Brown   Input Parameters:
361160225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3612a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3613552f7358SJed Brown 
3614552f7358SJed Brown   Output Parameter:
361520f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3616552f7358SJed Brown 
3617552f7358SJed Brown   Level: beginner
3618552f7358SJed Brown 
361960225df5SJacob Faibussowitsch   Fortran Notes:
3620a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3621a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
36223813dfbdSMatthew G Knepley 
36231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3624552f7358SJed Brown @*/
3625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3626d71ae5a4SJacob Faibussowitsch {
3627552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3628552f7358SJed Brown   PetscInt off;
3629552f7358SJed Brown 
3630552f7358SJed Brown   PetscFunctionBegin;
3631552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36324f572ea9SToby Isaac   PetscAssertPointer(support, 3);
36339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
36348e3a54c0SPierre Jolivet   *support = PetscSafePointerPlusOffset(mesh->supports, off);
36353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3636552f7358SJed Brown }
3637552f7358SJed Brown 
3638552f7358SJed Brown /*@
363992371b87SBarry Smith   DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers
3640552f7358SJed Brown 
3641a1cb98faSBarry Smith   Not Collective
3642552f7358SJed Brown 
3643552f7358SJed Brown   Input Parameters:
364460225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3645a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
364620f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3647552f7358SJed Brown 
3648552f7358SJed Brown   Level: beginner
3649552f7358SJed Brown 
3650a1cb98faSBarry Smith   Note:
3651a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3652a1cb98faSBarry Smith 
36531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3654552f7358SJed Brown @*/
3655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3656d71ae5a4SJacob Faibussowitsch {
3657552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3658552f7358SJed Brown   PetscInt pStart, pEnd;
3659552f7358SJed Brown   PetscInt dof, off, c;
3660552f7358SJed Brown 
3661552f7358SJed Brown   PetscFunctionBegin;
3662552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36654f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
36669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
366763a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3668552f7358SJed Brown   for (c = 0; c < dof; ++c) {
366963a3b9bcSJacob Faibussowitsch     PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd);
3670552f7358SJed Brown     mesh->supports[off + c] = support[c];
3671552f7358SJed Brown   }
36723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3673552f7358SJed Brown }
3674552f7358SJed Brown 
36757cd05799SMatthew G. Knepley /*@
3676eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
36777cd05799SMatthew G. Knepley 
3678a1cb98faSBarry Smith   Not Collective
36797cd05799SMatthew G. Knepley 
36807cd05799SMatthew G. Knepley   Input Parameters:
368160225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3682a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
36837cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
36847cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
36857cd05799SMatthew G. Knepley 
36867cd05799SMatthew G. Knepley   Level: beginner
36877cd05799SMatthew G. Knepley 
36881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
36897cd05799SMatthew G. Knepley @*/
3690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3691d71ae5a4SJacob Faibussowitsch {
3692552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3693552f7358SJed Brown   PetscInt pStart, pEnd;
3694552f7358SJed Brown   PetscInt dof, off;
3695552f7358SJed Brown 
3696552f7358SJed Brown   PetscFunctionBegin;
3697552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
37009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
370163a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
370263a3b9bcSJacob Faibussowitsch   PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd);
370363a3b9bcSJacob Faibussowitsch   PetscCheck(supportPos < dof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof);
3704552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
37053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3706552f7358SJed Brown }
3707552f7358SJed Brown 
3708b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3709d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3710d71ae5a4SJacob Faibussowitsch {
3711b5a892a1SMatthew G. Knepley   switch (ct) {
3712b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3713b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3714b5a892a1SMatthew G. Knepley     break;
3715b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3716b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3717b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3718b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3719b5a892a1SMatthew G. Knepley     break;
3720b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3721b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3722b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3723b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3724b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3725b5a892a1SMatthew G. Knepley     break;
3726d71ae5a4SJacob Faibussowitsch   default:
3727d71ae5a4SJacob Faibussowitsch     return o;
3728b5a892a1SMatthew G. Knepley   }
3729b5a892a1SMatthew G. Knepley   return o;
3730b5a892a1SMatthew G. Knepley }
3731b5a892a1SMatthew G. Knepley 
3732b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3733d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3734d71ae5a4SJacob Faibussowitsch {
3735b5a892a1SMatthew G. Knepley   switch (ct) {
3736b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3737b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3738b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3739b5a892a1SMatthew G. Knepley     break;
3740b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3741b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3742b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3743b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3744b5a892a1SMatthew G. Knepley     break;
3745b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3746b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3747b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3748b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3749b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3750b5a892a1SMatthew G. Knepley     break;
3751d71ae5a4SJacob Faibussowitsch   default:
3752d71ae5a4SJacob Faibussowitsch     return o;
3753b5a892a1SMatthew G. Knepley   }
3754b5a892a1SMatthew G. Knepley   return o;
3755b5a892a1SMatthew G. Knepley }
3756b5a892a1SMatthew G. Knepley 
3757b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3759d71ae5a4SJacob Faibussowitsch {
3760b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3761b5a892a1SMatthew G. Knepley 
3762b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
37639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3764b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3765b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3766b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3767b5a892a1SMatthew G. Knepley 
37689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
37699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
37709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3771b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3772b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3773b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3774b5a892a1SMatthew G. Knepley 
37759566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3776b5a892a1SMatthew G. Knepley       switch (ct) {
3777b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
37789566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37799566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3780b5a892a1SMatthew G. Knepley         break;
3781b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
37829566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37839566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37849566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3785b5a892a1SMatthew G. Knepley         break;
3786b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
37879566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37889566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37899566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
37909566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3791b5a892a1SMatthew G. Knepley         break;
3792d71ae5a4SJacob Faibussowitsch       default:
3793d71ae5a4SJacob Faibussowitsch         break;
3794b5a892a1SMatthew G. Knepley       }
3795b5a892a1SMatthew G. Knepley     }
3796b5a892a1SMatthew G. Knepley   }
37973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3798b5a892a1SMatthew G. Knepley }
3799b5a892a1SMatthew G. Knepley 
380009015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
380109015e70SStefano Zampini {
380209015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
380309015e70SStefano Zampini 
380409015e70SStefano Zampini   PetscFunctionBeginHot;
380509015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
380609015e70SStefano Zampini     if (useCone) {
380709015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
380809015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
380909015e70SStefano Zampini     } else {
381009015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
381109015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
381209015e70SStefano Zampini     }
381309015e70SStefano Zampini   } else {
381409015e70SStefano Zampini     if (useCone) {
381509015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
381609015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
381709015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
381809015e70SStefano Zampini 
381909015e70SStefano Zampini       *size = s->atlasDof[ps];
382009015e70SStefano Zampini       *arr  = mesh->cones + off;
382109015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
382209015e70SStefano Zampini     } else {
382309015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
382409015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
382509015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
382609015e70SStefano Zampini 
382709015e70SStefano Zampini       *size = s->atlasDof[ps];
382809015e70SStefano Zampini       *arr  = mesh->supports + off;
382909015e70SStefano Zampini     }
383009015e70SStefano Zampini   }
383109015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
383209015e70SStefano Zampini }
383309015e70SStefano Zampini 
383409015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
383509015e70SStefano Zampini {
383609015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
383709015e70SStefano Zampini 
383809015e70SStefano Zampini   PetscFunctionBeginHot;
383909015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
384009015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
384109015e70SStefano Zampini   }
384209015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
384309015e70SStefano Zampini }
384409015e70SStefano Zampini 
3845d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3846d71ae5a4SJacob Faibussowitsch {
3847b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3848b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3849b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3850b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3851b5a892a1SMatthew G. Knepley 
3852b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3853b5a892a1SMatthew G. Knepley   if (ornt) {
38549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3855476787b7SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN;
3856b5a892a1SMatthew G. Knepley   }
3857b5a892a1SMatthew G. Knepley   if (*points) {
3858b5a892a1SMatthew G. Knepley     closure = *points;
3859b5a892a1SMatthew G. Knepley   } else {
3860b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
38619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
38629566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3863b5a892a1SMatthew G. Knepley   }
386409015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3865b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3866b5a892a1SMatthew G. Knepley     closure[off++] = p;
3867b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3868b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3869b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3870b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3871b5a892a1SMatthew G. Knepley     }
3872b5a892a1SMatthew G. Knepley   } else {
387385036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt);
3874b5a892a1SMatthew G. Knepley 
3875b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3876b5a892a1SMatthew G. Knepley     closure[off++] = p;
3877b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3878b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3879b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3880b5a892a1SMatthew G. Knepley 
38819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3882b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3883b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3884b5a892a1SMatthew G. Knepley     }
3885b5a892a1SMatthew G. Knepley   }
388609015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3887b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3888b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3890b5a892a1SMatthew G. Knepley }
3891b5a892a1SMatthew G. Knepley 
3892d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3894d71ae5a4SJacob Faibussowitsch {
389585036b15SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
3896b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3897b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3898b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3899b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3900b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3901b5a892a1SMatthew G. Knepley 
3902b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
390409015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
39059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3906b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3907b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3908b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39099371c9d4SSatish Balay   if (*points) {
39109371c9d4SSatish Balay     pts = *points;
39119371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3912b5a892a1SMatthew G. Knepley   c        = 0;
3913b5a892a1SMatthew G. Knepley   pts[c++] = point;
3914b5a892a1SMatthew G. Knepley   pts[c++] = o;
39159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
39169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
39179371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39189371c9d4SSatish Balay     pts[c++] = closure[cl];
39199371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39209371c9d4SSatish Balay   }
39219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
39229371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39239371c9d4SSatish Balay     pts[c++] = closure[cl];
39249371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39259371c9d4SSatish Balay   }
39269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3927b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
39289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3929b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3930b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3931b5a892a1SMatthew G. Knepley   }
393209015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3933b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3934b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3935b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3936b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3937b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3938b5a892a1SMatthew G. Knepley 
39399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
394085036b15SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
394109015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3942b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3943b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3944b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3945b5a892a1SMatthew G. Knepley 
39469371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
39479371c9d4SSatish Balay           if (pts[i] == cp) break;
3948b5a892a1SMatthew G. Knepley         if (i == c) {
39499566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3950b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3951b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3952b5a892a1SMatthew G. Knepley         }
3953b5a892a1SMatthew G. Knepley       }
395409015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3955b5a892a1SMatthew G. Knepley     }
3956b5a892a1SMatthew G. Knepley   }
3957b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3958b5a892a1SMatthew G. Knepley   *points    = pts;
39593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3960b5a892a1SMatthew G. Knepley }
3961b5a892a1SMatthew G. Knepley 
3962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3963d71ae5a4SJacob Faibussowitsch {
3964b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3965b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3966b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3967b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3968b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3969b5a892a1SMatthew G. Knepley 
3970b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3972b5a892a1SMatthew G. Knepley   if (depth == 1) {
39739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
39743ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3975b5a892a1SMatthew G. Knepley   }
39769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3977476787b7SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN;
3978c306944fSJed Brown   if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
39799566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
39803ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3981b5a892a1SMatthew G. Knepley   }
39829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3983b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3984b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3985b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39869566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
39879371c9d4SSatish Balay   if (*points) {
39889371c9d4SSatish Balay     closure = *points;
39899371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3990b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3991b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3992b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3993b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3994b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3995b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3996b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3997b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3998b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3999b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
400085036b15SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangement(qt, o);
400109015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
4002b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
4003b5a892a1SMatthew G. Knepley 
4004b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
400585036b15SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2;
400663a3b9bcSJacob Faibussowitsch       PetscCheck(!o || !(o >= nO || o < -nO), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q);
4007b5a892a1SMatthew G. Knepley     }
400809015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4009b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
4010b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
4011b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
4012b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
40139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
4014b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
4015b5a892a1SMatthew G. Knepley       PetscInt       c;
4016b5a892a1SMatthew G. Knepley 
4017b5a892a1SMatthew G. Knepley       /* Check for duplicate */
4018b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
4019b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
4020b5a892a1SMatthew G. Knepley       }
4021b5a892a1SMatthew G. Knepley       if (c == closureSize) {
4022b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
4023b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
4024b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
4025b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
4026b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
4027b5a892a1SMatthew G. Knepley       }
4028b5a892a1SMatthew G. Knepley     }
402909015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4030b5a892a1SMatthew G. Knepley   }
40319566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
4032b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
4033b5a892a1SMatthew G. Knepley   if (points) *points = closure;
40343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4035b5a892a1SMatthew G. Knepley }
4036b5a892a1SMatthew G. Knepley 
4037552f7358SJed Brown /*@C
4038eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
4039552f7358SJed Brown 
4040a1cb98faSBarry Smith   Not Collective
4041552f7358SJed Brown 
4042552f7358SJed Brown   Input Parameters:
4043a1cb98faSBarry Smith + dm      - The `DMPLEX`
4044b5a892a1SMatthew G. Knepley . p       - The mesh point
4045a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
4046552f7358SJed Brown 
40476b867d5aSJose E. Roman   Input/Output Parameter:
40486b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
404920f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
40506b867d5aSJose E. Roman 
40516b867d5aSJose E. Roman   Output Parameter:
405220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4053552f7358SJed Brown 
4054a1cb98faSBarry Smith   Level: beginner
4055a1cb98faSBarry Smith 
4056552f7358SJed Brown   Note:
405720f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
4058552f7358SJed Brown 
405960225df5SJacob Faibussowitsch   Fortran Notes:
406020f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
40613813dfbdSMatthew G Knepley 
40621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4063552f7358SJed Brown @*/
4064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4065d71ae5a4SJacob Faibussowitsch {
4066b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4067552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40684f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
40694f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
40709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
40713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40729bf0dad6SMatthew G. Knepley }
40739bf0dad6SMatthew G. Knepley 
4074552f7358SJed Brown /*@C
4075eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
4076552f7358SJed Brown 
4077a1cb98faSBarry Smith   Not Collective
4078552f7358SJed Brown 
4079552f7358SJed Brown   Input Parameters:
4080a1cb98faSBarry Smith + dm        - The `DMPLEX`
4081b5a892a1SMatthew G. Knepley . p         - The mesh point
4082a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
408320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4084b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
4085552f7358SJed Brown 
4086a1cb98faSBarry Smith   Level: beginner
4087a1cb98faSBarry Smith 
4088552f7358SJed Brown   Note:
408920f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
4090552f7358SJed Brown 
40911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4092552f7358SJed Brown @*/
4093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4094d71ae5a4SJacob Faibussowitsch {
4095b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4096552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40974ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
40989566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
40993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4100552f7358SJed Brown }
4101552f7358SJed Brown 
4102552f7358SJed Brown /*@
4103eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
4104552f7358SJed Brown 
4105a1cb98faSBarry Smith   Not Collective
4106552f7358SJed Brown 
4107552f7358SJed Brown   Input Parameter:
410860225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4109552f7358SJed Brown 
4110552f7358SJed Brown   Output Parameters:
4111552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
4112552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
4113552f7358SJed Brown 
4114552f7358SJed Brown   Level: beginner
4115552f7358SJed Brown 
41161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
4117552f7358SJed Brown @*/
4118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
4119d71ae5a4SJacob Faibussowitsch {
4120552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
4121552f7358SJed Brown 
4122552f7358SJed Brown   PetscFunctionBegin;
4123552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41241baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
41251baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
41263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4127552f7358SJed Brown }
4128552f7358SJed Brown 
4129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
4130d71ae5a4SJacob Faibussowitsch {
4131552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
41326302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
4133552f7358SJed Brown 
4134552f7358SJed Brown   PetscFunctionBegin;
4135552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41369566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
41379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
41389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
41399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
41406302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41416302a7fbSVaclav Hapla   if (maxSupportSize) {
41429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
41439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
41449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
4145552f7358SJed Brown   }
41463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4147552f7358SJed Brown }
4148552f7358SJed Brown 
4149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
4150d71ae5a4SJacob Faibussowitsch {
4151552f7358SJed Brown   PetscFunctionBegin;
41529566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
4153dd072f5fSMatthew G. Knepley   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm));
4154ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
4155736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
415695602cf2SAlexis Marboeuf     PetscSF sfNatural;
4157f94b4a02SBlaise Bourdin 
41583dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
41599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
416095602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
4161c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
4162f94b4a02SBlaise Bourdin   }
41633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4164552f7358SJed Brown }
4165552f7358SJed Brown 
4166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
4167d71ae5a4SJacob Faibussowitsch {
41683dcd263cSBlaise Bourdin   PetscInt i = 0;
41692adcc780SMatthew G. Knepley 
41702adcc780SMatthew G. Knepley   PetscFunctionBegin;
41719566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
41729566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
4173c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
41743dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
41753dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
417695602cf2SAlexis Marboeuf       PetscSF sfNatural;
41773dcd263cSBlaise Bourdin 
41783dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
41799566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
4180c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
418195602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4182c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
41833dcd263cSBlaise Bourdin       break;
41843dcd263cSBlaise Bourdin     }
41853dcd263cSBlaise Bourdin   }
41863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41872adcc780SMatthew G. Knepley }
41882adcc780SMatthew G. Knepley 
4189552f7358SJed Brown /*@
4190eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4191552f7358SJed Brown 
4192a1cb98faSBarry Smith   Not Collective
4193552f7358SJed Brown 
4194552f7358SJed Brown   Input Parameter:
419560225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4196552f7358SJed Brown 
4197552f7358SJed Brown   Level: beginner
4198552f7358SJed Brown 
4199a1cb98faSBarry Smith   Note:
4200a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4201a1cb98faSBarry Smith 
42021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4203552f7358SJed Brown @*/
4204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4205d71ae5a4SJacob Faibussowitsch {
4206552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4207552f7358SJed Brown   PetscInt *offsets;
4208552f7358SJed Brown   PetscInt  supportSize;
4209552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4210552f7358SJed Brown 
4211552f7358SJed Brown   PetscFunctionBegin;
4212552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
421328b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
42149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4215552f7358SJed Brown   /* Calculate support sizes */
42169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4217552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4218552f7358SJed Brown     PetscInt dof, off, c;
4219552f7358SJed Brown 
42209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
422248a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4223552f7358SJed Brown   }
42249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4225552f7358SJed Brown   /* Calculate supports */
42269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
42279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
42289566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4229552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4230552f7358SJed Brown     PetscInt dof, off, c;
4231552f7358SJed Brown 
42329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4234552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4235552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4236552f7358SJed Brown       PetscInt       offS;
4237552f7358SJed Brown 
42389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
42390d644c17SKarl Rupp 
4240552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4241552f7358SJed Brown       ++offsets[q];
4242552f7358SJed Brown     }
4243552f7358SJed Brown   }
42449566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
42459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
42463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4247552f7358SJed Brown }
4248552f7358SJed Brown 
4249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4250d71ae5a4SJacob Faibussowitsch {
4251277ea44aSLisandro Dalcin   IS stratumIS;
4252277ea44aSLisandro Dalcin 
4253277ea44aSLisandro Dalcin   PetscFunctionBegin;
42543ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
425576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4256277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4257277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
42589566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4259277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
42609566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
42619371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
42629371c9d4SSatish Balay         overlap = PETSC_TRUE;
42639371c9d4SSatish Balay         break;
42649371c9d4SSatish Balay       }
4265277ea44aSLisandro Dalcin     }
426663a3b9bcSJacob Faibussowitsch     PetscCheck(!overlap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd);
4267277ea44aSLisandro Dalcin   }
42689566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
42699566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
42709566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
42713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4272277ea44aSLisandro Dalcin }
4273277ea44aSLisandro Dalcin 
4274e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label)
4275e91fa0a1SMatthew G. Knepley {
4276e91fa0a1SMatthew G. Knepley   PetscInt *pMin, *pMax;
4277e91fa0a1SMatthew G. Knepley   PetscInt  pStart, pEnd;
4278e91fa0a1SMatthew G. Knepley   PetscInt  dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT;
4279e91fa0a1SMatthew G. Knepley 
4280e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4281e91fa0a1SMatthew G. Knepley   {
4282e91fa0a1SMatthew G. Knepley     DMLabel label2;
4283e91fa0a1SMatthew G. Knepley 
4284e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellTypeLabel(dm, &label2));
4285e91fa0a1SMatthew G. Knepley     PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view"));
4286e91fa0a1SMatthew G. Knepley   }
4287e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4288e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4289e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4290e91fa0a1SMatthew G. Knepley 
4291e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4292e91fa0a1SMatthew G. Knepley     dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin);
4293e91fa0a1SMatthew G. Knepley     dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax);
4294e91fa0a1SMatthew G. Knepley   }
4295e91fa0a1SMatthew G. Knepley   PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax));
4296e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4297e91fa0a1SMatthew G. Knepley     pMin[d] = PETSC_MAX_INT;
4298e91fa0a1SMatthew G. Knepley     pMax[d] = PETSC_MIN_INT;
4299e91fa0a1SMatthew G. Knepley   }
4300e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4301e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4302e91fa0a1SMatthew G. Knepley     PetscInt       d;
4303e91fa0a1SMatthew G. Knepley 
4304e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4305e91fa0a1SMatthew G. Knepley     d       = DMPolytopeTypeGetDim(ct);
4306e91fa0a1SMatthew G. Knepley     pMin[d] = PetscMin(p, pMin[d]);
4307e91fa0a1SMatthew G. Knepley     pMax[d] = PetscMax(p, pMax[d]);
4308e91fa0a1SMatthew G. Knepley   }
4309e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4310e91fa0a1SMatthew G. Knepley     if (pMin[d] > pMax[d]) continue;
4311e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1));
4312e91fa0a1SMatthew G. Knepley   }
4313e91fa0a1SMatthew G. Knepley   PetscCall(PetscFree2(pMin, pMax));
4314e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4315e91fa0a1SMatthew G. Knepley }
4316e91fa0a1SMatthew G. Knepley 
4317e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label)
4318e91fa0a1SMatthew G. Knepley {
4319e91fa0a1SMatthew G. Knepley   PetscInt pStart, pEnd;
4320e91fa0a1SMatthew G. Knepley   PetscInt numRoots = 0, numLeaves = 0;
4321e91fa0a1SMatthew G. Knepley 
4322e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4323e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4324e91fa0a1SMatthew G. Knepley   {
4325e91fa0a1SMatthew G. Knepley     /* Initialize roots and count leaves */
4326e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4327e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4328e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4329e91fa0a1SMatthew G. Knepley 
4330e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4331e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4332e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4333e91fa0a1SMatthew G. Knepley       if (!coneSize && supportSize) {
4334e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4335e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4336e91fa0a1SMatthew G. Knepley         ++numRoots;
4337e91fa0a1SMatthew G. Knepley       } else if (!supportSize && coneSize) {
4338e91fa0a1SMatthew G. Knepley         ++numLeaves;
4339e91fa0a1SMatthew G. Knepley       } else if (!supportSize && !coneSize) {
4340e91fa0a1SMatthew G. Knepley         /* Isolated points */
4341e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4342e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4343e91fa0a1SMatthew G. Knepley       }
4344e91fa0a1SMatthew G. Knepley     }
4345e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4346e91fa0a1SMatthew G. Knepley   }
4347e91fa0a1SMatthew G. Knepley 
4348e91fa0a1SMatthew G. Knepley   if (numRoots + numLeaves == (pEnd - pStart)) {
4349e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4350e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4351e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4352e91fa0a1SMatthew G. Knepley 
4353e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4354e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4355e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4356e91fa0a1SMatthew G. Knepley       if (!supportSize && coneSize) {
4357e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4358e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4359e91fa0a1SMatthew G. Knepley       }
4360e91fa0a1SMatthew G. Knepley     }
4361e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4362e91fa0a1SMatthew G. Knepley   } else {
4363e91fa0a1SMatthew G. Knepley     PetscInt level = 0;
4364e91fa0a1SMatthew G. Knepley     PetscInt qStart, qEnd;
4365e91fa0a1SMatthew G. Knepley 
4366e91fa0a1SMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4367e91fa0a1SMatthew G. Knepley     while (qEnd > qStart) {
4368e91fa0a1SMatthew G. Knepley       PetscInt sMin = PETSC_MAX_INT;
4369e91fa0a1SMatthew G. Knepley       PetscInt sMax = PETSC_MIN_INT;
4370e91fa0a1SMatthew G. Knepley 
4371e91fa0a1SMatthew G. Knepley       for (PetscInt q = qStart; q < qEnd; ++q) {
4372e91fa0a1SMatthew G. Knepley         const PetscInt *support;
4373e91fa0a1SMatthew G. Knepley         PetscInt        supportSize;
4374e91fa0a1SMatthew G. Knepley 
4375e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
4376e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupport(dm, q, &support));
4377e91fa0a1SMatthew G. Knepley         for (PetscInt s = 0; s < supportSize; ++s) {
4378e91fa0a1SMatthew G. Knepley           sMin = PetscMin(support[s], sMin);
4379e91fa0a1SMatthew G. Knepley           sMax = PetscMax(support[s], sMax);
4380e91fa0a1SMatthew G. Knepley         }
4381e91fa0a1SMatthew G. Knepley       }
4382e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetNumValues(label, &level));
4383e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
4384e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4385e91fa0a1SMatthew G. Knepley     }
4386e91fa0a1SMatthew G. Knepley   }
4387e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4388e91fa0a1SMatthew G. Knepley }
4389e91fa0a1SMatthew G. Knepley 
4390552f7358SJed Brown /*@
4391a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4392552f7358SJed Brown 
439320f4b53cSBarry Smith   Collective
4394552f7358SJed Brown 
4395552f7358SJed Brown   Input Parameter:
439660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4397552f7358SJed Brown 
4398a1cb98faSBarry Smith   Level: beginner
4399552f7358SJed Brown 
4400552f7358SJed Brown   Notes:
4401a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4402a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4403a4e35b19SJacob Faibussowitsch 
4404a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4405a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4406a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4407b1bb481bSMatthew Knepley   meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on
4408a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4409a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4410a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4411552f7358SJed Brown 
4412b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4413b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4414b1bb481bSMatthew Knepley   we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose
4415b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4416a1cb98faSBarry Smith .vb
4417a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4418a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4419a1cb98faSBarry Smith .ve
4420a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4421a1cb98faSBarry Smith .vb
4422a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4423a1cb98faSBarry Smith    depth 1 = {e0, c0}
4424a1cb98faSBarry Smith .ve
4425b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4426b1bb481bSMatthew Knepley 
4427a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4428552f7358SJed Brown 
44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4430552f7358SJed Brown @*/
4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4432d71ae5a4SJacob Faibussowitsch {
4433df0420ecSMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
4434aa50250dSMatthew G. Knepley   DMLabel   label;
4435e91fa0a1SMatthew G. Knepley   PetscBool flg = PETSC_FALSE;
4436552f7358SJed Brown 
4437552f7358SJed Brown   PetscFunctionBegin;
4438552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4440277ea44aSLisandro Dalcin 
4441e91fa0a1SMatthew G. Knepley   // Create depth label
4442*d28dd301SMatthew G. Knepley   PetscCall(DMRemoveLabel(dm, "depth", NULL));
44439566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
44449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4445277ea44aSLisandro Dalcin 
4446e91fa0a1SMatthew G. Knepley   PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL));
4447e91fa0a1SMatthew G. Knepley   if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label));
4448e91fa0a1SMatthew G. Knepley   else PetscCall(DMPlexStratify_Topological_Private(dm, label));
4449552f7358SJed Brown 
4450bf4602e4SToby Isaac   { /* just in case there is an empty process */
4451bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4452bf4602e4SToby Isaac 
44539566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4454712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
445548a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4456bf4602e4SToby Isaac   }
44579566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
44589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
44593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4460552f7358SJed Brown }
4461552f7358SJed Brown 
4462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4463d71ae5a4SJacob Faibussowitsch {
4464412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4465412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4466ba2698f1SMatthew G. Knepley 
4467412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
44689566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
44699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
44709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4471ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4472ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4473ba2698f1SMatthew G. Knepley     switch (pdepth) {
4474d71ae5a4SJacob Faibussowitsch     case 0:
4475d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4476d71ae5a4SJacob Faibussowitsch       break;
4477ba2698f1SMatthew G. Knepley     case 1:
4478ba2698f1SMatthew G. Knepley       switch (coneSize) {
4479d71ae5a4SJacob Faibussowitsch       case 2:
4480d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4481d71ae5a4SJacob Faibussowitsch         break;
4482d71ae5a4SJacob Faibussowitsch       case 3:
4483d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4484d71ae5a4SJacob Faibussowitsch         break;
4485ba2698f1SMatthew G. Knepley       case 4:
4486ba2698f1SMatthew G. Knepley         switch (dim) {
4487d71ae5a4SJacob Faibussowitsch         case 2:
4488d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4489d71ae5a4SJacob Faibussowitsch           break;
4490d71ae5a4SJacob Faibussowitsch         case 3:
4491d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4492d71ae5a4SJacob Faibussowitsch           break;
4493d71ae5a4SJacob Faibussowitsch         default:
4494d71ae5a4SJacob Faibussowitsch           break;
4495ba2698f1SMatthew G. Knepley         }
4496ba2698f1SMatthew G. Knepley         break;
4497d71ae5a4SJacob Faibussowitsch       case 5:
4498d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4499d71ae5a4SJacob Faibussowitsch         break;
4500d71ae5a4SJacob Faibussowitsch       case 6:
4501d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4502d71ae5a4SJacob Faibussowitsch         break;
4503d71ae5a4SJacob Faibussowitsch       case 8:
4504d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4505d71ae5a4SJacob Faibussowitsch         break;
4506d71ae5a4SJacob Faibussowitsch       default:
4507d71ae5a4SJacob Faibussowitsch         break;
4508ba2698f1SMatthew G. Knepley       }
4509ba2698f1SMatthew G. Knepley     }
4510ba2698f1SMatthew G. Knepley   } else {
4511ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4512ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4513ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4514ba2698f1SMatthew G. Knepley       switch (dim) {
4515ba2698f1SMatthew G. Knepley       case 1:
4516ba2698f1SMatthew G. Knepley         switch (coneSize) {
4517d71ae5a4SJacob Faibussowitsch         case 2:
4518d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4519d71ae5a4SJacob Faibussowitsch           break;
4520d71ae5a4SJacob Faibussowitsch         default:
4521d71ae5a4SJacob Faibussowitsch           break;
4522ba2698f1SMatthew G. Knepley         }
4523ba2698f1SMatthew G. Knepley         break;
4524ba2698f1SMatthew G. Knepley       case 2:
4525ba2698f1SMatthew G. Knepley         switch (coneSize) {
4526d71ae5a4SJacob Faibussowitsch         case 3:
4527d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4528d71ae5a4SJacob Faibussowitsch           break;
4529d71ae5a4SJacob Faibussowitsch         case 4:
4530d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4531d71ae5a4SJacob Faibussowitsch           break;
4532d71ae5a4SJacob Faibussowitsch         default:
4533d71ae5a4SJacob Faibussowitsch           break;
4534ba2698f1SMatthew G. Knepley         }
4535ba2698f1SMatthew G. Knepley         break;
4536ba2698f1SMatthew G. Knepley       case 3:
4537ba2698f1SMatthew G. Knepley         switch (coneSize) {
4538d71ae5a4SJacob Faibussowitsch         case 4:
4539d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4540d71ae5a4SJacob Faibussowitsch           break;
45419371c9d4SSatish Balay         case 5: {
4542da9060c4SMatthew G. Knepley           const PetscInt *cone;
4543da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4544da9060c4SMatthew G. Knepley 
45459566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
45469566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4547da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4548d71ae5a4SJacob Faibussowitsch           case 3:
4549d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4550d71ae5a4SJacob Faibussowitsch             break;
4551d71ae5a4SJacob Faibussowitsch           case 4:
4552d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4553d71ae5a4SJacob Faibussowitsch             break;
4554da9060c4SMatthew G. Knepley           }
45559371c9d4SSatish Balay         } break;
4556d71ae5a4SJacob Faibussowitsch         case 6:
4557d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4558d71ae5a4SJacob Faibussowitsch           break;
4559d71ae5a4SJacob Faibussowitsch         default:
4560d71ae5a4SJacob Faibussowitsch           break;
4561ba2698f1SMatthew G. Knepley         }
4562ba2698f1SMatthew G. Knepley         break;
4563d71ae5a4SJacob Faibussowitsch       default:
4564d71ae5a4SJacob Faibussowitsch         break;
4565ba2698f1SMatthew G. Knepley       }
4566ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4567ba2698f1SMatthew G. Knepley       switch (coneSize) {
4568d71ae5a4SJacob Faibussowitsch       case 2:
4569d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4570d71ae5a4SJacob Faibussowitsch         break;
4571d71ae5a4SJacob Faibussowitsch       case 3:
4572d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4573d71ae5a4SJacob Faibussowitsch         break;
4574d71ae5a4SJacob Faibussowitsch       case 4:
4575d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4576d71ae5a4SJacob Faibussowitsch         break;
4577d71ae5a4SJacob Faibussowitsch       default:
4578d71ae5a4SJacob Faibussowitsch         break;
4579ba2698f1SMatthew G. Knepley       }
4580ba2698f1SMatthew G. Knepley     }
4581ba2698f1SMatthew G. Knepley   }
4582412e9a14SMatthew G. Knepley   *pt = ct;
45833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4584ba2698f1SMatthew G. Knepley }
4585412e9a14SMatthew G. Knepley 
4586412e9a14SMatthew G. Knepley /*@
4587412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4588412e9a14SMatthew G. Knepley 
458920f4b53cSBarry Smith   Collective
4590412e9a14SMatthew G. Knepley 
4591412e9a14SMatthew G. Knepley   Input Parameter:
459260225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4593412e9a14SMatthew G. Knepley 
4594412e9a14SMatthew G. Knepley   Level: developer
4595412e9a14SMatthew G. Knepley 
4596a1cb98faSBarry Smith   Note:
4597a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4598a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4599a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4600412e9a14SMatthew G. Knepley 
4601a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4602a1cb98faSBarry Smith 
46031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4604412e9a14SMatthew G. Knepley @*/
4605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4606d71ae5a4SJacob Faibussowitsch {
4607412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4608412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4609412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4610412e9a14SMatthew G. Knepley 
4611412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4612412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4613412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
46149566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
46159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
46169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
461721027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
461821027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4619412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4620327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4621412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4622412e9a14SMatthew G. Knepley 
46239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
46249566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
4625476787b7SMatthew 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);
46269566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
462721027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4628412e9a14SMatthew G. Knepley   }
46299566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
46309566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
46313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4632ba2698f1SMatthew G. Knepley }
4633ba2698f1SMatthew G. Knepley 
4634552f7358SJed Brown /*@C
4635552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4636552f7358SJed Brown 
4637552f7358SJed Brown   Not Collective
4638552f7358SJed Brown 
4639552f7358SJed Brown   Input Parameters:
4640a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4641552f7358SJed Brown . numPoints - The number of input points for the join
4642552f7358SJed Brown - points    - The input points
4643552f7358SJed Brown 
4644552f7358SJed Brown   Output Parameters:
4645552f7358SJed Brown + numCoveredPoints - The number of points in the join
4646552f7358SJed Brown - coveredPoints    - The points in the join
4647552f7358SJed Brown 
4648552f7358SJed Brown   Level: intermediate
4649552f7358SJed Brown 
4650a1cb98faSBarry Smith   Note:
4651a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4652552f7358SJed Brown 
465360225df5SJacob Faibussowitsch   Fortran Notes:
465420f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46553813dfbdSMatthew G Knepley 
46561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4657552f7358SJed Brown @*/
4658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4659d71ae5a4SJacob Faibussowitsch {
4660552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4661552f7358SJed Brown   PetscInt *join[2];
4662552f7358SJed Brown   PetscInt  joinSize, i = 0;
4663552f7358SJed Brown   PetscInt  dof, off, p, c, m;
46646302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4665552f7358SJed Brown 
4666552f7358SJed Brown   PetscFunctionBegin;
4667552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46684f572ea9SToby Isaac   PetscAssertPointer(points, 3);
46694f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
46704f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
46716302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
46726302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
46736302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4674552f7358SJed Brown   /* Copy in support of first point */
46759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
46769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4677ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4678552f7358SJed Brown   /* Check each successive support */
4679552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4680552f7358SJed Brown     PetscInt newJoinSize = 0;
4681552f7358SJed Brown 
46829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
46839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4684552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4685552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4686552f7358SJed Brown 
4687552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4688552f7358SJed Brown         if (point == join[i][m]) {
4689552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4690552f7358SJed Brown           break;
4691552f7358SJed Brown         }
4692552f7358SJed Brown       }
4693552f7358SJed Brown     }
4694552f7358SJed Brown     joinSize = newJoinSize;
4695552f7358SJed Brown     i        = 1 - i;
4696552f7358SJed Brown   }
4697552f7358SJed Brown   *numCoveredPoints = joinSize;
4698552f7358SJed Brown   *coveredPoints    = join[i];
46996302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
47003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4701552f7358SJed Brown }
4702552f7358SJed Brown 
4703552f7358SJed Brown /*@C
4704552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4705552f7358SJed Brown 
4706552f7358SJed Brown   Not Collective
4707552f7358SJed Brown 
4708552f7358SJed Brown   Input Parameters:
4709a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4710552f7358SJed Brown . numPoints - The number of input points for the join
4711552f7358SJed Brown - points    - The input points
4712552f7358SJed Brown 
4713552f7358SJed Brown   Output Parameters:
4714552f7358SJed Brown + numCoveredPoints - The number of points in the join
4715552f7358SJed Brown - coveredPoints    - The points in the join
4716552f7358SJed Brown 
4717552f7358SJed Brown   Level: intermediate
4718552f7358SJed Brown 
471960225df5SJacob Faibussowitsch   Fortran Notes:
472020f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4721a1cb98faSBarry Smith 
47221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4723552f7358SJed Brown @*/
4724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4725d71ae5a4SJacob Faibussowitsch {
4726552f7358SJed Brown   PetscFunctionBegin;
4727552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47284f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
47294f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
47304f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
47319566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4732d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
47333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4734552f7358SJed Brown }
4735552f7358SJed Brown 
4736552f7358SJed Brown /*@C
4737552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4738552f7358SJed Brown 
4739552f7358SJed Brown   Not Collective
4740552f7358SJed Brown 
4741552f7358SJed Brown   Input Parameters:
4742a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4743552f7358SJed Brown . numPoints - The number of input points for the join
4744552f7358SJed Brown - points    - The input points
4745552f7358SJed Brown 
4746552f7358SJed Brown   Output Parameters:
4747552f7358SJed Brown + numCoveredPoints - The number of points in the join
4748552f7358SJed Brown - coveredPoints    - The points in the join
4749552f7358SJed Brown 
4750552f7358SJed Brown   Level: intermediate
4751552f7358SJed Brown 
475260225df5SJacob Faibussowitsch   Fortran Notes:
475320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4754a1cb98faSBarry Smith 
47551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4756552f7358SJed Brown @*/
4757d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4758d71ae5a4SJacob Faibussowitsch {
4759552f7358SJed Brown   PetscInt *offsets, **closures;
4760552f7358SJed Brown   PetscInt *join[2];
4761552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
476224c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4763552f7358SJed Brown 
4764552f7358SJed Brown   PetscFunctionBegin;
4765552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47664f572ea9SToby Isaac   PetscAssertPointer(points, 3);
47674f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
47684f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4769552f7358SJed Brown 
47709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
47719566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
47729566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
47736302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
477424c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
47759566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
47769566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4777552f7358SJed Brown 
4778552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4779552f7358SJed Brown     PetscInt closureSize;
4780552f7358SJed Brown 
47819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
47820d644c17SKarl Rupp 
4783552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4784552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4785552f7358SJed Brown       PetscInt pStart, pEnd, i;
4786552f7358SJed Brown 
47879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4788552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4789552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4790552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4791552f7358SJed Brown           break;
4792552f7358SJed Brown         }
4793552f7358SJed Brown       }
4794552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4795552f7358SJed Brown     }
479663a3b9bcSJacob 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);
4797552f7358SJed Brown   }
4798552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4799552f7358SJed Brown     PetscInt dof;
4800552f7358SJed Brown 
4801552f7358SJed Brown     /* Copy in support of first point */
4802552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4803ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4804552f7358SJed Brown     /* Check each successive cone */
4805552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4806552f7358SJed Brown       PetscInt newJoinSize = 0;
4807552f7358SJed Brown 
4808552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4809552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4810552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4811552f7358SJed Brown 
4812552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4813552f7358SJed Brown           if (point == join[i][m]) {
4814552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4815552f7358SJed Brown             break;
4816552f7358SJed Brown           }
4817552f7358SJed Brown         }
4818552f7358SJed Brown       }
4819552f7358SJed Brown       joinSize = newJoinSize;
4820552f7358SJed Brown       i        = 1 - i;
4821552f7358SJed Brown     }
4822552f7358SJed Brown     if (joinSize) break;
4823552f7358SJed Brown   }
4824552f7358SJed Brown   *numCoveredPoints = joinSize;
4825552f7358SJed Brown   *coveredPoints    = join[i];
482648a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
48279566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
48289566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
48296302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
48303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4831552f7358SJed Brown }
4832552f7358SJed Brown 
4833552f7358SJed Brown /*@C
4834552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4835552f7358SJed Brown 
4836552f7358SJed Brown   Not Collective
4837552f7358SJed Brown 
4838552f7358SJed Brown   Input Parameters:
4839a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4840552f7358SJed Brown . numPoints - The number of input points for the meet
4841552f7358SJed Brown - points    - The input points
4842552f7358SJed Brown 
4843552f7358SJed Brown   Output Parameters:
484460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet
484560225df5SJacob Faibussowitsch - coveringPoints    - The points in the meet
4846552f7358SJed Brown 
4847552f7358SJed Brown   Level: intermediate
4848552f7358SJed Brown 
4849a1cb98faSBarry Smith   Note:
4850a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4851552f7358SJed Brown 
48523813dfbdSMatthew G Knepley   Fortran Notes:
485320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
48543813dfbdSMatthew G Knepley 
48551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4856552f7358SJed Brown @*/
4857d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4858d71ae5a4SJacob Faibussowitsch {
4859552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4860552f7358SJed Brown   PetscInt *meet[2];
4861552f7358SJed Brown   PetscInt  meetSize, i = 0;
4862552f7358SJed Brown   PetscInt  dof, off, p, c, m;
48636302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4864552f7358SJed Brown 
4865552f7358SJed Brown   PetscFunctionBegin;
4866552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48674f572ea9SToby Isaac   PetscAssertPointer(points, 3);
48684f572ea9SToby Isaac   PetscAssertPointer(numCoveringPoints, 4);
48694f572ea9SToby Isaac   PetscAssertPointer(coveringPoints, 5);
48706302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
48716302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
48726302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4873552f7358SJed Brown   /* Copy in cone of first point */
48749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
48759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4876ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4877552f7358SJed Brown   /* Check each successive cone */
4878552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4879552f7358SJed Brown     PetscInt newMeetSize = 0;
4880552f7358SJed Brown 
48819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
48829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4883552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4884552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4885552f7358SJed Brown 
4886552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4887552f7358SJed Brown         if (point == meet[i][m]) {
4888552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4889552f7358SJed Brown           break;
4890552f7358SJed Brown         }
4891552f7358SJed Brown       }
4892552f7358SJed Brown     }
4893552f7358SJed Brown     meetSize = newMeetSize;
4894552f7358SJed Brown     i        = 1 - i;
4895552f7358SJed Brown   }
4896552f7358SJed Brown   *numCoveringPoints = meetSize;
4897552f7358SJed Brown   *coveringPoints    = meet[i];
48986302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
48993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4900552f7358SJed Brown }
4901552f7358SJed Brown 
4902552f7358SJed Brown /*@C
4903552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4904552f7358SJed Brown 
4905552f7358SJed Brown   Not Collective
4906552f7358SJed Brown 
4907552f7358SJed Brown   Input Parameters:
4908a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4909552f7358SJed Brown . numPoints - The number of input points for the meet
4910552f7358SJed Brown - points    - The input points
4911552f7358SJed Brown 
4912552f7358SJed Brown   Output Parameters:
4913552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4914552f7358SJed Brown - coveredPoints    - The points in the meet
4915552f7358SJed Brown 
4916552f7358SJed Brown   Level: intermediate
4917552f7358SJed Brown 
491860225df5SJacob Faibussowitsch   Fortran Notes:
491920f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49203813dfbdSMatthew G Knepley 
49211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4922552f7358SJed Brown @*/
4923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4924d71ae5a4SJacob Faibussowitsch {
4925552f7358SJed Brown   PetscFunctionBegin;
4926552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49274f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
49284f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
49294f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
49309566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4931d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
49323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4933552f7358SJed Brown }
4934552f7358SJed Brown 
4935552f7358SJed Brown /*@C
4936552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4937552f7358SJed Brown 
4938552f7358SJed Brown   Not Collective
4939552f7358SJed Brown 
4940552f7358SJed Brown   Input Parameters:
4941a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4942552f7358SJed Brown . numPoints - The number of input points for the meet
4943552f7358SJed Brown - points    - The input points
4944552f7358SJed Brown 
4945552f7358SJed Brown   Output Parameters:
4946552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4947552f7358SJed Brown - coveredPoints    - The points in the meet
4948552f7358SJed Brown 
4949552f7358SJed Brown   Level: intermediate
4950552f7358SJed Brown 
495160225df5SJacob Faibussowitsch   Fortran Notes:
495220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
49533813dfbdSMatthew G Knepley 
49541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4955552f7358SJed Brown @*/
4956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4957d71ae5a4SJacob Faibussowitsch {
4958552f7358SJed Brown   PetscInt *offsets, **closures;
4959552f7358SJed Brown   PetscInt *meet[2];
4960552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
496124c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4962552f7358SJed Brown 
4963552f7358SJed Brown   PetscFunctionBegin;
4964552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49654f572ea9SToby Isaac   PetscAssertPointer(points, 3);
49664f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
49674f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4968552f7358SJed Brown 
49699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
49709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
49719566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
49726302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
497324c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
49749566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
49759566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4976552f7358SJed Brown 
4977552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4978552f7358SJed Brown     PetscInt closureSize;
4979552f7358SJed Brown 
49809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
49810d644c17SKarl Rupp 
4982552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4983552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4984552f7358SJed Brown       PetscInt pStart, pEnd, i;
4985552f7358SJed Brown 
49869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4987552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4988552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4989552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4990552f7358SJed Brown           break;
4991552f7358SJed Brown         }
4992552f7358SJed Brown       }
4993552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4994552f7358SJed Brown     }
499563a3b9bcSJacob 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);
4996552f7358SJed Brown   }
4997552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4998552f7358SJed Brown     PetscInt dof;
4999552f7358SJed Brown 
5000552f7358SJed Brown     /* Copy in cone of first point */
5001552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
5002ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
5003552f7358SJed Brown     /* Check each successive cone */
5004552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
5005552f7358SJed Brown       PetscInt newMeetSize = 0;
5006552f7358SJed Brown 
5007552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
5008552f7358SJed Brown       for (c = 0; c < dof; ++c) {
5009552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
5010552f7358SJed Brown 
5011552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
5012552f7358SJed Brown           if (point == meet[i][m]) {
5013552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
5014552f7358SJed Brown             break;
5015552f7358SJed Brown           }
5016552f7358SJed Brown         }
5017552f7358SJed Brown       }
5018552f7358SJed Brown       meetSize = newMeetSize;
5019552f7358SJed Brown       i        = 1 - i;
5020552f7358SJed Brown     }
5021552f7358SJed Brown     if (meetSize) break;
5022552f7358SJed Brown   }
5023552f7358SJed Brown   *numCoveredPoints = meetSize;
5024552f7358SJed Brown   *coveredPoints    = meet[i];
502548a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
50269566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
50279566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
50286302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
50293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5030552f7358SJed Brown }
5031552f7358SJed Brown 
50324e3744c5SMatthew G. Knepley /*@C
5033a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
50344e3744c5SMatthew G. Knepley 
50354e3744c5SMatthew G. Knepley   Not Collective
50364e3744c5SMatthew G. Knepley 
50374e3744c5SMatthew G. Knepley   Input Parameters:
5038a1cb98faSBarry Smith + dmA - A `DMPLEX` object
5039a1cb98faSBarry Smith - dmB - A `DMPLEX` object
50404e3744c5SMatthew G. Knepley 
50412fe279fdSBarry Smith   Output Parameter:
5042a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
50434e3744c5SMatthew G. Knepley 
50444e3744c5SMatthew G. Knepley   Level: intermediate
50454e3744c5SMatthew G. Knepley 
5046a1cb98faSBarry Smith   Note:
50473c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
50484e3744c5SMatthew G. Knepley 
50491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
50504e3744c5SMatthew G. Knepley @*/
5051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
5052d71ae5a4SJacob Faibussowitsch {
50534e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
50544e3744c5SMatthew G. Knepley 
50554e3744c5SMatthew G. Knepley   PetscFunctionBegin;
50564e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
50574e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
50584f572ea9SToby Isaac   PetscAssertPointer(equal, 3);
50594e3744c5SMatthew G. Knepley 
50604e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
50619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
50629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
50633ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
50649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
50659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
50663ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
50674e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
50684e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
50694e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
50704e3744c5SMatthew G. Knepley 
50719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
50729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
50739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
50749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
50759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
50769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
50773ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50784e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
50793ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50803ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
50814e3744c5SMatthew G. Knepley     }
50829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
50839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
50849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
50859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
50863ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
50874e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
50883ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
50894e3744c5SMatthew G. Knepley     }
50904e3744c5SMatthew G. Knepley   }
50914e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
50923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50934e3744c5SMatthew G. Knepley }
50944e3744c5SMatthew G. Knepley 
50957cd05799SMatthew G. Knepley /*@C
50967cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
50977cd05799SMatthew G. Knepley 
50987cd05799SMatthew G. Knepley   Not Collective
50997cd05799SMatthew G. Knepley 
51007cd05799SMatthew G. Knepley   Input Parameters:
5101a1cb98faSBarry Smith + dm         - The `DMPLEX`
51027cd05799SMatthew G. Knepley . cellDim    - The cell dimension
51037cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
51047cd05799SMatthew G. Knepley 
51052fe279fdSBarry Smith   Output Parameter:
51067cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
51077cd05799SMatthew G. Knepley 
51087cd05799SMatthew G. Knepley   Level: developer
51097cd05799SMatthew G. Knepley 
5110a1cb98faSBarry Smith   Note:
51117cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
51127cd05799SMatthew G. Knepley 
51131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
51147cd05799SMatthew G. Knepley @*/
5115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
5116d71ae5a4SJacob Faibussowitsch {
511782f516ccSBarry Smith   MPI_Comm comm;
5118552f7358SJed Brown 
5119552f7358SJed Brown   PetscFunctionBegin;
51209566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
51214f572ea9SToby Isaac   PetscAssertPointer(numFaceVertices, 4);
5122552f7358SJed Brown   switch (cellDim) {
5123d71ae5a4SJacob Faibussowitsch   case 0:
5124d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
5125d71ae5a4SJacob Faibussowitsch     break;
5126d71ae5a4SJacob Faibussowitsch   case 1:
5127d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
5128d71ae5a4SJacob Faibussowitsch     break;
5129552f7358SJed Brown   case 2:
5130552f7358SJed Brown     switch (numCorners) {
513119436ca2SJed Brown     case 3:                 /* triangle */
513219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5133552f7358SJed Brown       break;
513419436ca2SJed Brown     case 4:                 /* quadrilateral */
513519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
5136552f7358SJed Brown       break;
513719436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
513819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5139552f7358SJed Brown       break;
514019436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
514119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
5142552f7358SJed Brown       break;
5143d71ae5a4SJacob Faibussowitsch     default:
5144d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5145552f7358SJed Brown     }
5146552f7358SJed Brown     break;
5147552f7358SJed Brown   case 3:
5148552f7358SJed Brown     switch (numCorners) {
514919436ca2SJed Brown     case 4:                 /* tetradehdron */
515019436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
5151552f7358SJed Brown       break;
515219436ca2SJed Brown     case 6:                 /* tet cohesive cells */
515319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5154552f7358SJed Brown       break;
515519436ca2SJed Brown     case 8:                 /* hexahedron */
515619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
5157552f7358SJed Brown       break;
515819436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
515919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5160552f7358SJed Brown       break;
516119436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
516219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5163552f7358SJed Brown       break;
516419436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
516519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5166552f7358SJed Brown       break;
516719436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
516819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
5169552f7358SJed Brown       break;
517019436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
517119436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
5172552f7358SJed Brown       break;
5173d71ae5a4SJacob Faibussowitsch     default:
5174d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
5175552f7358SJed Brown     }
5176552f7358SJed Brown     break;
5177d71ae5a4SJacob Faibussowitsch   default:
5178d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
5179552f7358SJed Brown   }
51803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5181552f7358SJed Brown }
5182552f7358SJed Brown 
5183552f7358SJed Brown /*@
5184a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
5185552f7358SJed Brown 
5186552f7358SJed Brown   Not Collective
5187552f7358SJed Brown 
5188aa50250dSMatthew G. Knepley   Input Parameter:
5189a1cb98faSBarry Smith . dm - The `DMPLEX` object
5190552f7358SJed Brown 
5191aa50250dSMatthew G. Knepley   Output Parameter:
5192a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
5193552f7358SJed Brown 
5194552f7358SJed Brown   Level: developer
5195552f7358SJed Brown 
51961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
5197aa50250dSMatthew G. Knepley @*/
5198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
5199d71ae5a4SJacob Faibussowitsch {
5200aa50250dSMatthew G. Knepley   PetscFunctionBegin;
5201aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52024f572ea9SToby Isaac   PetscAssertPointer(depthLabel, 2);
5203c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
52043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5205aa50250dSMatthew G. Knepley }
5206aa50250dSMatthew G. Knepley 
5207aa50250dSMatthew G. Knepley /*@
5208aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
5209aa50250dSMatthew G. Knepley 
5210aa50250dSMatthew G. Knepley   Not Collective
5211aa50250dSMatthew G. Knepley 
5212aa50250dSMatthew G. Knepley   Input Parameter:
5213a1cb98faSBarry Smith . dm - The `DMPLEX` object
5214aa50250dSMatthew G. Knepley 
5215aa50250dSMatthew G. Knepley   Output Parameter:
5216aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
5217aa50250dSMatthew G. Knepley 
5218aa50250dSMatthew G. Knepley   Level: developer
5219552f7358SJed Brown 
5220b1bb481bSMatthew Knepley   Notes:
5221a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
5222a1cb98faSBarry Smith 
5223a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
5224a1cb98faSBarry Smith 
5225dc287ab2SVaclav Hapla   An empty mesh gives -1.
5226b1bb481bSMatthew Knepley 
52271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
5228552f7358SJed Brown @*/
5229d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
5230d71ae5a4SJacob Faibussowitsch {
52319f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5232aa50250dSMatthew G. Knepley   DMLabel  label;
5233aa50250dSMatthew G. Knepley   PetscInt d = 0;
5234552f7358SJed Brown 
5235552f7358SJed Brown   PetscFunctionBegin;
5236552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52374f572ea9SToby Isaac   PetscAssertPointer(depth, 2);
52389f4ada15SMatthew G. Knepley   if (mesh->tr) {
52399f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
52409f4ada15SMatthew G. Knepley   } else {
52419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
52429566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
5243552f7358SJed Brown     *depth = d - 1;
52449f4ada15SMatthew G. Knepley   }
52453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5246552f7358SJed Brown }
5247552f7358SJed Brown 
5248552f7358SJed Brown /*@
524920f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
5250552f7358SJed Brown 
5251552f7358SJed Brown   Not Collective
5252552f7358SJed Brown 
5253552f7358SJed Brown   Input Parameters:
5254a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5255570fa34dSVaclav Hapla - depth - The requested depth
5256552f7358SJed Brown 
5257552f7358SJed Brown   Output Parameters:
525820f4b53cSBarry Smith + start - The first point at this `depth`
525920f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
5260552f7358SJed Brown 
5261552f7358SJed Brown   Level: developer
5262552f7358SJed Brown 
5263a1cb98faSBarry Smith   Notes:
5264a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
5265a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
5266a1cb98faSBarry Smith   higher dimension, e.g., "edges".
5267a1cb98faSBarry Smith 
52682827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
5269552f7358SJed Brown @*/
5270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
5271d71ae5a4SJacob Faibussowitsch {
52729f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5273aa50250dSMatthew G. Knepley   DMLabel  label;
527463d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
5275552f7358SJed Brown 
5276552f7358SJed Brown   PetscFunctionBegin;
5277552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52789371c9d4SSatish Balay   if (start) {
52794f572ea9SToby Isaac     PetscAssertPointer(start, 3);
52809371c9d4SSatish Balay     *start = 0;
52819371c9d4SSatish Balay   }
52829371c9d4SSatish Balay   if (end) {
52834f572ea9SToby Isaac     PetscAssertPointer(end, 4);
52849371c9d4SSatish Balay     *end = 0;
52859371c9d4SSatish Balay   }
52869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
52873ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5288570fa34dSVaclav Hapla   if (depth < 0) {
528963d1a920SMatthew G. Knepley     if (start) *start = pStart;
529063d1a920SMatthew G. Knepley     if (end) *end = pEnd;
52913ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5292552f7358SJed Brown   }
52939f4ada15SMatthew G. Knepley   if (mesh->tr) {
52949f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
52959f4ada15SMatthew G. Knepley   } else {
52969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
529728b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5298570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
52999f4ada15SMatthew G. Knepley   }
53003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5301552f7358SJed Brown }
5302552f7358SJed Brown 
5303552f7358SJed Brown /*@
530420f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5305552f7358SJed Brown 
5306552f7358SJed Brown   Not Collective
5307552f7358SJed Brown 
5308552f7358SJed Brown   Input Parameters:
5309a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5310570fa34dSVaclav Hapla - height - The requested height
5311552f7358SJed Brown 
5312552f7358SJed Brown   Output Parameters:
531320f4b53cSBarry Smith + start - The first point at this `height`
531420f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5315552f7358SJed Brown 
5316552f7358SJed Brown   Level: developer
5317552f7358SJed Brown 
5318a1cb98faSBarry Smith   Notes:
5319a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5320a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5321a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5322a1cb98faSBarry Smith 
53232827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5324552f7358SJed Brown @*/
5325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5326d71ae5a4SJacob Faibussowitsch {
5327aa50250dSMatthew G. Knepley   DMLabel  label;
532863d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5329552f7358SJed Brown 
5330552f7358SJed Brown   PetscFunctionBegin;
5331552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53329371c9d4SSatish Balay   if (start) {
53334f572ea9SToby Isaac     PetscAssertPointer(start, 3);
53349371c9d4SSatish Balay     *start = 0;
53359371c9d4SSatish Balay   }
53369371c9d4SSatish Balay   if (end) {
53374f572ea9SToby Isaac     PetscAssertPointer(end, 4);
53389371c9d4SSatish Balay     *end = 0;
53399371c9d4SSatish Balay   }
53409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
53413ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5342570fa34dSVaclav Hapla   if (height < 0) {
534363d1a920SMatthew G. Knepley     if (start) *start = pStart;
534463d1a920SMatthew G. Knepley     if (end) *end = pEnd;
53453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5346552f7358SJed Brown   }
53479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
534859e4dc13SStefano Zampini   if (label) PetscCall(DMLabelGetNumValues(label, &depth));
534959e4dc13SStefano Zampini   else PetscCall(DMGetDimension(dm, &depth));
535059e4dc13SStefano Zampini   PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed");
535159e4dc13SStefano Zampini   PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end));
53523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5353552f7358SJed Brown }
5354552f7358SJed Brown 
5355ba2698f1SMatthew G. Knepley /*@
535620f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5357ba2698f1SMatthew G. Knepley 
5358ba2698f1SMatthew G. Knepley   Not Collective
5359ba2698f1SMatthew G. Knepley 
5360d8d19677SJose E. Roman   Input Parameters:
5361a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5362ba2698f1SMatthew G. Knepley - point - The point
5363ba2698f1SMatthew G. Knepley 
5364ba2698f1SMatthew G. Knepley   Output Parameter:
536520f4b53cSBarry Smith . depth - The depth of the `point`
5366ba2698f1SMatthew G. Knepley 
5367ba2698f1SMatthew G. Knepley   Level: intermediate
5368ba2698f1SMatthew G. Knepley 
53691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5370ba2698f1SMatthew G. Knepley @*/
5371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5372d71ae5a4SJacob Faibussowitsch {
5373ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5374ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53754f572ea9SToby Isaac   PetscAssertPointer(depth, 3);
53769566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
53773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5378ba2698f1SMatthew G. Knepley }
5379ba2698f1SMatthew G. Knepley 
5380ba2698f1SMatthew G. Knepley /*@
538120f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
53820c0a32dcSVaclav Hapla 
53830c0a32dcSVaclav Hapla   Not Collective
53840c0a32dcSVaclav Hapla 
5385d8d19677SJose E. Roman   Input Parameters:
5386a1cb98faSBarry Smith + dm    - The `DMPLEX` object
53870c0a32dcSVaclav Hapla - point - The point
53880c0a32dcSVaclav Hapla 
53890c0a32dcSVaclav Hapla   Output Parameter:
539020f4b53cSBarry Smith . height - The height of the `point`
53910c0a32dcSVaclav Hapla 
53920c0a32dcSVaclav Hapla   Level: intermediate
53930c0a32dcSVaclav Hapla 
53941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
53950c0a32dcSVaclav Hapla @*/
5396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5397d71ae5a4SJacob Faibussowitsch {
53980c0a32dcSVaclav Hapla   PetscInt n, pDepth;
53990c0a32dcSVaclav Hapla 
54000c0a32dcSVaclav Hapla   PetscFunctionBegin;
54010c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54024f572ea9SToby Isaac   PetscAssertPointer(height, 3);
54039566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
54049566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
54050c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
54063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54070c0a32dcSVaclav Hapla }
54080c0a32dcSVaclav Hapla 
54090c0a32dcSVaclav Hapla /*@
5410a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5411ba2698f1SMatthew G. Knepley 
5412ba2698f1SMatthew G. Knepley   Not Collective
5413ba2698f1SMatthew G. Knepley 
5414ba2698f1SMatthew G. Knepley   Input Parameter:
5415a1cb98faSBarry Smith . dm - The `DMPLEX` object
5416ba2698f1SMatthew G. Knepley 
5417ba2698f1SMatthew G. Knepley   Output Parameter:
5418a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5419412e9a14SMatthew G. Knepley 
5420ba2698f1SMatthew G. Knepley   Level: developer
5421ba2698f1SMatthew G. Knepley 
5422a1cb98faSBarry Smith   Note:
5423a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5424a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5425a1cb98faSBarry Smith 
54261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5427ba2698f1SMatthew G. Knepley @*/
5428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5429d71ae5a4SJacob Faibussowitsch {
5430ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5431ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54324f572ea9SToby Isaac   PetscAssertPointer(celltypeLabel, 2);
54339566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5434ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
54353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5436ba2698f1SMatthew G. Knepley }
5437ba2698f1SMatthew G. Knepley 
5438ba2698f1SMatthew G. Knepley /*@
5439ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5440ba2698f1SMatthew G. Knepley 
5441ba2698f1SMatthew G. Knepley   Not Collective
5442ba2698f1SMatthew G. Knepley 
5443d8d19677SJose E. Roman   Input Parameters:
5444a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5445ba2698f1SMatthew G. Knepley - cell - The cell
5446ba2698f1SMatthew G. Knepley 
5447ba2698f1SMatthew G. Knepley   Output Parameter:
5448ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5449ba2698f1SMatthew G. Knepley 
5450ba2698f1SMatthew G. Knepley   Level: intermediate
5451ba2698f1SMatthew G. Knepley 
54521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5453ba2698f1SMatthew G. Knepley @*/
5454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5455d71ae5a4SJacob Faibussowitsch {
54569f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5457ba2698f1SMatthew G. Knepley   DMLabel  label;
5458ba2698f1SMatthew G. Knepley   PetscInt ct;
5459ba2698f1SMatthew G. Knepley 
5460ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5461ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
54624f572ea9SToby Isaac   PetscAssertPointer(celltype, 3);
54639f4ada15SMatthew G. Knepley   if (mesh->tr) {
54649f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
54659f4ada15SMatthew G. Knepley   } else {
546621027e53SStefano Zampini     PetscInt pStart, pEnd;
546721027e53SStefano Zampini 
546821027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
546921027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
547021027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
547121027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
547221027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
547321027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
547421027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
547521027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
547621027e53SStefano Zampini       }
547721027e53SStefano Zampini     }
547821027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
547921027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
54809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
54819566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
548263a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5483936381afSPierre Jolivet       PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
548421027e53SStefano Zampini     }
54859f4ada15SMatthew G. Knepley   }
54863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5487ba2698f1SMatthew G. Knepley }
5488ba2698f1SMatthew G. Knepley 
5489412e9a14SMatthew G. Knepley /*@
5490412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5491412e9a14SMatthew G. Knepley 
5492412e9a14SMatthew G. Knepley   Not Collective
5493412e9a14SMatthew G. Knepley 
5494412e9a14SMatthew G. Knepley   Input Parameters:
5495a1cb98faSBarry Smith + dm       - The `DMPLEX` object
5496412e9a14SMatthew G. Knepley . cell     - The cell
5497412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5498412e9a14SMatthew G. Knepley 
5499a1cb98faSBarry Smith   Level: advanced
5500a1cb98faSBarry Smith 
5501a1cb98faSBarry Smith   Note:
5502a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5503412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5504412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5505db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5506412e9a14SMatthew G. Knepley 
55071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5508412e9a14SMatthew G. Knepley @*/
5509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5510d71ae5a4SJacob Faibussowitsch {
551121027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5512412e9a14SMatthew G. Knepley   DMLabel  label;
551321027e53SStefano Zampini   PetscInt pStart, pEnd;
5514412e9a14SMatthew G. Knepley 
5515412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5516412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
551721027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
55189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
55199566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
552021027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
552121027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
55223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5523412e9a14SMatthew G. Knepley }
5524412e9a14SMatthew G. Knepley 
5525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5526d71ae5a4SJacob Faibussowitsch {
5527efe440bfSMatthew G. Knepley   PetscSection section, s;
5528efe440bfSMatthew G. Knepley   Mat          m;
55293e922f36SToby Isaac   PetscInt     maxHeight;
5530dd4c3f67SMatthew G. Knepley   const char  *prefix;
5531552f7358SJed Brown 
5532552f7358SJed Brown   PetscFunctionBegin;
55339566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5534dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5535dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5536dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
55379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
55389566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
55399566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
55409566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
55419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
55429566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
55439566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
55449566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
55459566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
55469566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
55478f4c458bSMatthew G. Knepley 
55489566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
55499566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5550dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5551dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
55523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5553552f7358SJed Brown }
5554552f7358SJed Brown 
5555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5556d71ae5a4SJacob Faibussowitsch {
55576858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
55586858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5559f19dbd58SToby Isaac 
5560f19dbd58SToby Isaac   PetscFunctionBegin;
5561f19dbd58SToby Isaac   *field = NULL;
55629566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
55639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
55646858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
55656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5566f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
55676858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
55686858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5569f19dbd58SToby Isaac   }
55703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5571f19dbd58SToby Isaac }
5572f19dbd58SToby Isaac 
55737cd05799SMatthew G. Knepley /*@C
55747cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
55757cd05799SMatthew G. Knepley 
55767cd05799SMatthew G. Knepley   Not Collective
55777cd05799SMatthew G. Knepley 
55782fe279fdSBarry Smith   Input Parameter:
5579a1cb98faSBarry Smith . dm - The `DMPLEX` object
55807cd05799SMatthew G. Knepley 
55817cd05799SMatthew G. Knepley   Output Parameter:
5582a1cb98faSBarry Smith . section - The `PetscSection` object
55837cd05799SMatthew G. Knepley 
55847cd05799SMatthew G. Knepley   Level: developer
55857cd05799SMatthew G. Knepley 
55861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
55877cd05799SMatthew G. Knepley @*/
5588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5589d71ae5a4SJacob Faibussowitsch {
5590552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5591552f7358SJed Brown 
5592552f7358SJed Brown   PetscFunctionBegin;
5593552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5594552f7358SJed Brown   if (section) *section = mesh->coneSection;
55953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5596552f7358SJed Brown }
5597552f7358SJed Brown 
55987cd05799SMatthew G. Knepley /*@C
55997cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
56007cd05799SMatthew G. Knepley 
56017cd05799SMatthew G. Knepley   Not Collective
56027cd05799SMatthew G. Knepley 
56032fe279fdSBarry Smith   Input Parameter:
5604a1cb98faSBarry Smith . dm - The `DMPLEX` object
56057cd05799SMatthew G. Knepley 
56067cd05799SMatthew G. Knepley   Output Parameter:
5607a1cb98faSBarry Smith . section - The `PetscSection` object
56087cd05799SMatthew G. Knepley 
56097cd05799SMatthew G. Knepley   Level: developer
56107cd05799SMatthew G. Knepley 
56111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
56127cd05799SMatthew G. Knepley @*/
5613d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5614d71ae5a4SJacob Faibussowitsch {
56158cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
56168cb4d582SMatthew G. Knepley 
56178cb4d582SMatthew G. Knepley   PetscFunctionBegin;
56188cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56198cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
56203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56218cb4d582SMatthew G. Knepley }
56228cb4d582SMatthew G. Knepley 
56237cd05799SMatthew G. Knepley /*@C
56247cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
56257cd05799SMatthew G. Knepley 
56267cd05799SMatthew G. Knepley   Not Collective
56277cd05799SMatthew G. Knepley 
56282fe279fdSBarry Smith   Input Parameter:
5629a1cb98faSBarry Smith . dm - The `DMPLEX` object
56307cd05799SMatthew G. Knepley 
56317cd05799SMatthew G. Knepley   Output Parameter:
56327cd05799SMatthew G. Knepley . cones - The cone for each point
56337cd05799SMatthew G. Knepley 
56347cd05799SMatthew G. Knepley   Level: developer
56357cd05799SMatthew G. Knepley 
56361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
56377cd05799SMatthew G. Knepley @*/
5638d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5639d71ae5a4SJacob Faibussowitsch {
5640552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5641552f7358SJed Brown 
5642552f7358SJed Brown   PetscFunctionBegin;
5643552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5644552f7358SJed Brown   if (cones) *cones = mesh->cones;
56453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5646552f7358SJed Brown }
5647552f7358SJed Brown 
56487cd05799SMatthew G. Knepley /*@C
56497cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
56507cd05799SMatthew G. Knepley 
56517cd05799SMatthew G. Knepley   Not Collective
56527cd05799SMatthew G. Knepley 
56532fe279fdSBarry Smith   Input Parameter:
5654a1cb98faSBarry Smith . dm - The `DMPLEX` object
56557cd05799SMatthew G. Knepley 
56567cd05799SMatthew G. Knepley   Output Parameter:
5657b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
56587cd05799SMatthew G. Knepley 
56597cd05799SMatthew G. Knepley   Level: developer
56607cd05799SMatthew G. Knepley 
5661b5a892a1SMatthew G. Knepley   Notes:
5662a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5663b5a892a1SMatthew G. Knepley 
5664a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5665b5a892a1SMatthew G. Knepley 
56661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
56677cd05799SMatthew G. Knepley @*/
5668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5669d71ae5a4SJacob Faibussowitsch {
5670552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5671552f7358SJed Brown 
5672552f7358SJed Brown   PetscFunctionBegin;
5673552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5674552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
56753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5676552f7358SJed Brown }
5677552f7358SJed Brown 
5678552f7358SJed Brown /******************************** FEM Support **********************************/
5679552f7358SJed Brown 
5680d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
5681d2b2dc1eSMatthew G. Knepley {
5682d2b2dc1eSMatthew G. Knepley   PetscInt depth;
5683d2b2dc1eSMatthew G. Knepley 
5684d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
5685d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
5686d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS));
5687d2b2dc1eSMatthew G. Knepley   if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS));
5688d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5689d2b2dc1eSMatthew G. Knepley }
5690d2b2dc1eSMatthew G. Knepley 
56915962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS)
56925962854dSMatthew G. Knepley {
56935962854dSMatthew G. Knepley   PetscInt depth;
56945962854dSMatthew G. Knepley 
56955962854dSMatthew G. Knepley   PetscFunctionBegin;
56965962854dSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
56975962854dSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS));
56985962854dSMatthew G. Knepley   if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS));
56995962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
57005962854dSMatthew G. Knepley }
57015962854dSMatthew G. Knepley 
57029e8305c2SJed Brown /*
57039e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
57049e8305c2SJed Brown  representing a line in the section.
57059e8305c2SJed Brown */
57065f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor)
5707d71ae5a4SJacob Faibussowitsch {
5708e327e467SRezgar Shakeri   PetscObject  obj;
5709e327e467SRezgar Shakeri   PetscClassId id;
5710e327e467SRezgar Shakeri   PetscFE      fe = NULL;
5711e327e467SRezgar Shakeri 
57129e8305c2SJed Brown   PetscFunctionBeginHot;
57139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5714e327e467SRezgar Shakeri   PetscCall(DMGetField(dm, field, NULL, &obj));
5715e327e467SRezgar Shakeri   PetscCall(PetscObjectGetClassId(obj, &id));
5716e327e467SRezgar Shakeri   if (id == PETSCFE_CLASSID) fe = (PetscFE)obj;
5717e327e467SRezgar Shakeri 
5718e327e467SRezgar Shakeri   if (!fe) {
5719e327e467SRezgar Shakeri     /* Assume the full interpolated mesh is in the chart; lines in particular */
57209e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
57219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
57229e8305c2SJed Brown     *k = *k / *Nc + 1;
5723e327e467SRezgar Shakeri   } else {
5724e327e467SRezgar Shakeri     PetscInt       dual_space_size, dim;
57255f82726aSMatthew G. Knepley     PetscDualSpace dsp;
57265f82726aSMatthew G. Knepley 
5727e327e467SRezgar Shakeri     PetscCall(DMGetDimension(dm, &dim));
57285f82726aSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(fe, &dsp));
57295f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size));
5730e327e467SRezgar Shakeri     *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1;
57315f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous));
57325f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor));
57335f82726aSMatthew G. Knepley   }
57345f82726aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
57355f82726aSMatthew G. Knepley }
57365f82726aSMatthew G. Knepley 
57375f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof)
57385f82726aSMatthew G. Knepley {
57395f82726aSMatthew G. Knepley   PetscFunctionBeginHot;
57405f82726aSMatthew G. Knepley   if (tensor) {
57415f82726aSMatthew G. Knepley     *dof = PetscPowInt(k + 1, dim);
57425f82726aSMatthew G. Knepley   } else {
57435f82726aSMatthew G. Knepley     switch (dim) {
57445f82726aSMatthew G. Knepley     case 1:
57455f82726aSMatthew G. Knepley       *dof = k + 1;
57465f82726aSMatthew G. Knepley       break;
57475f82726aSMatthew G. Knepley     case 2:
57485f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2)) / 2;
57495f82726aSMatthew G. Knepley       break;
57505f82726aSMatthew G. Knepley     case 3:
57515f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2) * (k + 3)) / 6;
57525f82726aSMatthew G. Knepley       break;
57535f82726aSMatthew G. Knepley     default:
57545f82726aSMatthew G. Knepley       *dof = 0;
57555f82726aSMatthew G. Knepley     }
57569e8305c2SJed Brown   }
57573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57589e8305c2SJed Brown }
57599e8305c2SJed Brown 
5760a4355906SMatthew Knepley /*@
5761bc1eb3faSJed Brown 
5762bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5763bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
576420f4b53cSBarry Smith   section provided (or the section of the `DM`).
5765a4355906SMatthew Knepley 
5766a4355906SMatthew Knepley   Input Parameters:
576720f4b53cSBarry Smith + dm      - The `DM`
576820f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
576920f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5770a4355906SMatthew Knepley 
5771bc1eb3faSJed Brown   Example:
5772bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5773bc1eb3faSJed Brown .vb
5774bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5775bc1eb3faSJed Brown 
5776bc1eb3faSJed Brown   v4 -- e6 -- v3
5777bc1eb3faSJed Brown   |           |
5778bc1eb3faSJed Brown   e7    c0    e8
5779bc1eb3faSJed Brown   |           |
5780bc1eb3faSJed Brown   v1 -- e5 -- v2
5781bc1eb3faSJed Brown .ve
5782bc1eb3faSJed Brown 
5783bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5784bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5785bc1eb3faSJed Brown .vb
5786bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5787bc1eb3faSJed Brown     v1 -> [4]
5788bc1eb3faSJed Brown     ...
5789bc1eb3faSJed Brown     e5 -> [8, 9]
5790bc1eb3faSJed Brown .ve
5791bc1eb3faSJed Brown 
5792bc1eb3faSJed Brown   which corresponds to the dofs
5793bc1eb3faSJed Brown .vb
5794bc1eb3faSJed Brown     6   10  11  7
5795bc1eb3faSJed Brown     13  2   3   15
5796bc1eb3faSJed Brown     12  0   1   14
5797bc1eb3faSJed Brown     4   8   9   5
5798bc1eb3faSJed Brown .ve
5799bc1eb3faSJed Brown 
5800bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5801bc1eb3faSJed Brown .vb
5802bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5803bc1eb3faSJed Brown .ve
5804bc1eb3faSJed Brown 
5805bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5806bc1eb3faSJed Brown .vb
5807bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5808bc1eb3faSJed Brown .ve
5809bc1eb3faSJed Brown 
5810a4355906SMatthew Knepley   Level: developer
5811a4355906SMatthew Knepley 
5812da9ac489SAlbert Cowie   Notes:
5813a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5814a1cb98faSBarry Smith   degree of the basis.
5815a1cb98faSBarry Smith 
5816da9ac489SAlbert Cowie   This is required to run with libCEED.
5817da9ac489SAlbert Cowie 
58181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5819a4355906SMatthew Knepley @*/
5820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5821d71ae5a4SJacob Faibussowitsch {
58227391a63aSMatthew G. Knepley   DMLabel   label;
5823bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
58245f82726aSMatthew G. Knepley   PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE;
58253194fc30SMatthew G. Knepley 
58263194fc30SMatthew G. Knepley   PetscFunctionBegin;
58279566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58283ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5829a433471fSStefano Zampini   if (point < 0) {
5830a433471fSStefano Zampini     PetscInt sStart, sEnd;
5831a433471fSStefano Zampini 
58329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5833a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5834a433471fSStefano Zampini   }
58359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
58369566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
58379566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58389371c9d4SSatish Balay   if (depth == 1) {
58399371c9d4SSatish Balay     eStart = point;
58409371c9d4SSatish Balay   } else if (depth == dim) {
58417391a63aSMatthew G. Knepley     const PetscInt *cone;
58427391a63aSMatthew G. Knepley 
58439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5844d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5845d4e6627bSStefano Zampini     else if (dim == 3) {
5846d4e6627bSStefano Zampini       const PetscInt *cone2;
58479566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5848d4e6627bSStefano Zampini       eStart = cone2[0];
584963a3b9bcSJacob 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);
585063a3b9bcSJacob 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);
5851e327e467SRezgar Shakeri 
58529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5853bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5854bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5855bb197d40SJed Brown     PetscInt *perm;
5856bb197d40SJed Brown 
58573194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
58585f82726aSMatthew G. Knepley       PetscInt dof;
58595f82726aSMatthew G. Knepley 
58605f82726aSMatthew G. Knepley       PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58615f82726aSMatthew 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);
58625f82726aSMatthew G. Knepley       if (!continuous && d < dim) continue;
58635f82726aSMatthew G. Knepley       PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58645f82726aSMatthew G. Knepley       size += dof * Nc;
58653194fc30SMatthew G. Knepley     }
58669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
58673194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5868bb197d40SJed Brown       switch (d) {
5869babf31e0SJed Brown       case 1:
58705f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58715f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
5872babf31e0SJed Brown         /*
5873babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5874babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5875babf31e0SJed Brown          */
5876e327e467SRezgar Shakeri         if (continuous) {
5877babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
58789371c9d4SSatish Balay           for (i = 0; i < k - 1; i++)
58799371c9d4SSatish Balay             for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5880babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5881babf31e0SJed Brown           foffset = offset;
5882e327e467SRezgar Shakeri         } else {
58835f82726aSMatthew G. Knepley           PetscInt dof;
58845f82726aSMatthew G. Knepley 
58855f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58865f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
58875f82726aSMatthew G. Knepley           foffset = offset;
5888e327e467SRezgar Shakeri         }
5889babf31e0SJed Brown         break;
589089eabcffSMatthew G. Knepley       case 2:
58913194fc30SMatthew 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} */
58925f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58935f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
58943194fc30SMatthew G. Knepley         /* The SEM order is
58953194fc30SMatthew G. Knepley 
58963194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
589789eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
58983194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
58993194fc30SMatthew G. Knepley          */
5900e327e467SRezgar Shakeri         if (continuous) {
59013194fc30SMatthew G. Knepley           const PetscInt of   = 0;
59023194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
59033194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
59043194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
59053194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
59063194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
59073194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
59083194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
59093194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
59103194fc30SMatthew G. Knepley           PetscInt       o;
59113194fc30SMatthew G. Knepley 
59123194fc30SMatthew G. Knepley           /* bottom */
59133194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
59149371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
59159371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59163194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
59173194fc30SMatthew G. Knepley           /* middle */
59183194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
59193194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
59209371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
59219371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59223194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
59233194fc30SMatthew G. Knepley           }
59243194fc30SMatthew G. Knepley           /* top */
59253194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
59269371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
59279371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59283194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
59293194fc30SMatthew G. Knepley           foffset = offset;
5930e327e467SRezgar Shakeri         } else {
59315f82726aSMatthew G. Knepley           PetscInt dof;
59325f82726aSMatthew G. Knepley 
59335f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
59345f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
59355f82726aSMatthew G. Knepley           foffset = offset;
59363194fc30SMatthew G. Knepley         }
593789eabcffSMatthew G. Knepley         break;
593889eabcffSMatthew G. Knepley       case 3:
593989eabcffSMatthew G. Knepley         /* The original hex closure is
594089eabcffSMatthew G. Knepley 
594189eabcffSMatthew G. Knepley          {c,
594289eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
594389eabcffSMatthew 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,
594489eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
594589eabcffSMatthew G. Knepley          */
59465f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
59475f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
594889eabcffSMatthew G. Knepley         /* The SEM order is
594989eabcffSMatthew G. Knepley          Bottom Slice
595089eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
595189eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
595289eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
595389eabcffSMatthew G. Knepley 
595489eabcffSMatthew G. Knepley          Middle Slice (j)
595589eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
595689eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
595789eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
595889eabcffSMatthew G. Knepley 
595989eabcffSMatthew G. Knepley          Top Slice
596089eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
596189eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
596289eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
596389eabcffSMatthew G. Knepley          */
5964e327e467SRezgar Shakeri         if (continuous) {
596589eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
596689eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
596789eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
596889eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
596989eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
597089eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
597189eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
597289eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
597389eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
597489eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
597589eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
597689eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
597789eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
597889eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
597989eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
598089eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
598189eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
598289eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
598389eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
598489eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
598589eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
598689eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
598789eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
598889eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
598989eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
599089eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
599189eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
599289eabcffSMatthew G. Knepley           PetscInt       o, n;
599389eabcffSMatthew G. Knepley 
599489eabcffSMatthew G. Knepley           /* Bottom Slice */
599589eabcffSMatthew G. Knepley           /*   bottom */
599689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
59979371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
59989371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
599989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
600089eabcffSMatthew G. Knepley           /*   middle */
600189eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
600289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
60039371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
60049371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
60059371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
60069371c9d4SSatish Balay             }
600789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
60083194fc30SMatthew G. Knepley           }
600989eabcffSMatthew G. Knepley           /*   top */
601089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
60119371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
60129371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
601389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
601489eabcffSMatthew G. Knepley 
601589eabcffSMatthew G. Knepley           /* Middle Slice */
601689eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
601789eabcffSMatthew G. Knepley             /*   bottom */
601889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
60199371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
60209371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
602189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
602289eabcffSMatthew G. Knepley             /*   middle */
602389eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
602489eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
60259371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
60269371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
602789eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
602889eabcffSMatthew G. Knepley             }
602989eabcffSMatthew G. Knepley             /*   top */
603089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
60319371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
60329371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
603389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
603489eabcffSMatthew G. Knepley           }
603589eabcffSMatthew G. Knepley 
603689eabcffSMatthew G. Knepley           /* Top Slice */
603789eabcffSMatthew G. Knepley           /*   bottom */
603889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
60399371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
60409371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
604189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
604289eabcffSMatthew G. Knepley           /*   middle */
604389eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
604489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
60459371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
60469371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
604789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
604889eabcffSMatthew G. Knepley           }
604989eabcffSMatthew G. Knepley           /*   top */
605089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
60519371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
60529371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
605389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
605489eabcffSMatthew G. Knepley 
605589eabcffSMatthew G. Knepley           foffset = offset;
6056e327e467SRezgar Shakeri         } else {
60575f82726aSMatthew G. Knepley           PetscInt dof;
60585f82726aSMatthew G. Knepley 
60595f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
60605f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
60615f82726aSMatthew G. Knepley           foffset = offset;
606289eabcffSMatthew G. Knepley         }
606389eabcffSMatthew G. Knepley         break;
6064d71ae5a4SJacob Faibussowitsch       default:
6065d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
606689eabcffSMatthew G. Knepley       }
606789eabcffSMatthew G. Knepley     }
606863a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
60693194fc30SMatthew G. Knepley     /* Check permutation */
60703194fc30SMatthew G. Knepley     {
60713194fc30SMatthew G. Knepley       PetscInt *check;
60723194fc30SMatthew G. Knepley 
60739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
60741dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
60751dca8a05SBarry Smith         check[i] = -1;
60761dca8a05SBarry 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]);
60771dca8a05SBarry Smith       }
60783194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
60791dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
60809566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
60813194fc30SMatthew G. Knepley     }
60829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
6083a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
6084a05c9aa3SJed Brown       PetscInt *loc_perm;
60859566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
6086a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
6087a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
6088a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
6089a05c9aa3SJed Brown       }
60909566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
6091a05c9aa3SJed Brown     }
6092bb197d40SJed Brown   }
60933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60943194fc30SMatthew G. Knepley }
60953194fc30SMatthew G. Knepley 
6096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
6097d71ae5a4SJacob Faibussowitsch {
6098e071409bSToby Isaac   PetscDS  prob;
6099e071409bSToby Isaac   PetscInt depth, Nf, h;
6100e071409bSToby Isaac   DMLabel  label;
6101e071409bSToby Isaac 
6102e071409bSToby Isaac   PetscFunctionBeginHot;
61039566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
6104e071409bSToby Isaac   Nf      = prob->Nf;
6105e071409bSToby Isaac   label   = dm->depthLabel;
6106e071409bSToby Isaac   *dspace = NULL;
6107e071409bSToby Isaac   if (field < Nf) {
6108e071409bSToby Isaac     PetscObject disc = prob->disc[field];
6109e071409bSToby Isaac 
6110e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
6111e071409bSToby Isaac       PetscDualSpace dsp;
6112e071409bSToby Isaac 
61139566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
61149566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
61159566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
6116e071409bSToby Isaac       h = depth - 1 - h;
6117e071409bSToby Isaac       if (h) {
61189566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
6119e071409bSToby Isaac       } else {
6120e071409bSToby Isaac         *dspace = dsp;
6121e071409bSToby Isaac       }
6122e071409bSToby Isaac     }
6123e071409bSToby Isaac   }
61243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6125e071409bSToby Isaac }
6126e071409bSToby Isaac 
6127d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6128d71ae5a4SJacob Faibussowitsch {
612928351e22SJed Brown   PetscScalar       *array;
613028351e22SJed Brown   const PetscScalar *vArray;
6131d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
61321a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
6133552f7358SJed Brown 
61341b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61393f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
61409df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
61419df71ca4SMatthew G. Knepley       PetscInt dof;
6142d9917b9dSMatthew G. Knepley 
61439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
61449df71ca4SMatthew G. Knepley       size += dof;
61459df71ca4SMatthew G. Knepley     }
61469df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
61479df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
61482a3aaacfSMatthew G. Knepley       PetscInt       dof;
61495a1bb5cfSMatthew G. Knepley 
61505a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
61519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
61525a1bb5cfSMatthew G. Knepley       size += dof;
61535a1bb5cfSMatthew G. Knepley     }
61543f7cbbe7SMatthew G. Knepley     if (!values) {
61553f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
61563ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
61573f7cbbe7SMatthew G. Knepley     }
61589566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
6159982e9ed1SMatthew G. Knepley   } else {
6160982e9ed1SMatthew G. Knepley     array = *values;
6161982e9ed1SMatthew G. Knepley   }
61629df71ca4SMatthew G. Knepley   size = 0;
616328351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
61649df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
61659df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
616628351e22SJed Brown     const PetscScalar *varr;
6167d9917b9dSMatthew G. Knepley 
61689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
61699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
61708e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
6171ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61729df71ca4SMatthew G. Knepley     size += dof;
61739df71ca4SMatthew G. Knepley   }
61749df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
61759df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
61769df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
61775a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
617828351e22SJed Brown     const PetscScalar *varr;
61795a1bb5cfSMatthew G. Knepley 
618052ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
61819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
61829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
61838e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
61845a1bb5cfSMatthew G. Knepley     if (o >= 0) {
6185ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61865a1bb5cfSMatthew G. Knepley     } else {
6187ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
61885a1bb5cfSMatthew G. Knepley     }
61899df71ca4SMatthew G. Knepley     size += dof;
61905a1bb5cfSMatthew G. Knepley   }
619128351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
61929df71ca4SMatthew G. Knepley   if (!*values) {
61935a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
61945a1bb5cfSMatthew G. Knepley     *values = array;
61959df71ca4SMatthew G. Knepley   } else {
619663a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
61978c312ff3SMatthew G. Knepley     *csize = size;
61989df71ca4SMatthew G. Knepley   }
61993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62005a1bb5cfSMatthew G. Knepley }
6201d9917b9dSMatthew G. Knepley 
620227f02ce8SMatthew G. Knepley /* Compress out points not in the section */
6203d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
6204d71ae5a4SJacob Faibussowitsch {
620527f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
620627f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
620727f02ce8SMatthew G. Knepley 
62089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
620927f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
621027f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
621127f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
621227f02ce8SMatthew G. Knepley       points[q * 2]     = r;
621327f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
621427f02ce8SMatthew G. Knepley       ++q;
621527f02ce8SMatthew G. Knepley     }
621627f02ce8SMatthew G. Knepley   }
621727f02ce8SMatthew G. Knepley   *numPoints = q;
62183ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
621927f02ce8SMatthew G. Knepley }
622027f02ce8SMatthew G. Knepley 
622197529cf3SJed Brown /* Compressed closure does not apply closure permutation */
622207218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6223d71ae5a4SJacob Faibussowitsch {
622427f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
6225923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
6226923c78e0SToby Isaac 
6227923c78e0SToby Isaac   PetscFunctionBeginHot;
62289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
622907218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
6230923c78e0SToby Isaac     PetscInt dof, off;
6231923c78e0SToby Isaac 
62329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
62339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
62349566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
6235923c78e0SToby Isaac     np  = dof / 2;
62368e3a54c0SPierre Jolivet     pts = PetscSafePointerPlusOffset((PetscInt *)cla, off);
623727f02ce8SMatthew G. Knepley   } else {
623807218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
62399566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
6240923c78e0SToby Isaac   }
6241923c78e0SToby Isaac   *numPoints = np;
6242923c78e0SToby Isaac   *points    = pts;
6243923c78e0SToby Isaac   *clp       = cla;
62443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6245923c78e0SToby Isaac }
6246923c78e0SToby Isaac 
6247d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6248d71ae5a4SJacob Faibussowitsch {
6249923c78e0SToby Isaac   PetscFunctionBeginHot;
6250923c78e0SToby Isaac   if (!*clPoints) {
62519566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
6252923c78e0SToby Isaac   } else {
62539566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
6254923c78e0SToby Isaac   }
6255923c78e0SToby Isaac   *numPoints = 0;
6256923c78e0SToby Isaac   *points    = NULL;
6257923c78e0SToby Isaac   *clSec     = NULL;
6258923c78e0SToby Isaac   *clPoints  = NULL;
6259923c78e0SToby Isaac   *clp       = NULL;
62603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6261923c78e0SToby Isaac }
6262923c78e0SToby Isaac 
6263d71ae5a4SJacob 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[])
6264d71ae5a4SJacob Faibussowitsch {
62651a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
626697e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
626797e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
62681a271a75SMatthew G. Knepley 
62691a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6270fe02ba77SJed Brown   *size = 0;
62719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
627297e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
627397e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
627497e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
627597e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
62761a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
62771a271a75SMatthew G. Knepley     const PetscScalar *varr;
62781a271a75SMatthew G. Knepley 
62799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
62809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
62818e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
628297e99dd9SToby Isaac     if (clperm) {
628397e99dd9SToby Isaac       if (perm) {
628497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
62851a271a75SMatthew G. Knepley       } else {
628697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
628797e99dd9SToby Isaac       }
628897e99dd9SToby Isaac       if (flip) {
628997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
629097e99dd9SToby Isaac       }
629197e99dd9SToby Isaac     } else {
629297e99dd9SToby Isaac       if (perm) {
629397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
629497e99dd9SToby Isaac       } else {
629597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
629697e99dd9SToby Isaac       }
629797e99dd9SToby Isaac       if (flip) {
629897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
62991a271a75SMatthew G. Knepley       }
63001a271a75SMatthew G. Knepley     }
630197e99dd9SToby Isaac     offset += dof;
630297e99dd9SToby Isaac   }
63039566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
63041a271a75SMatthew G. Knepley   *size = offset;
63053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63061a271a75SMatthew G. Knepley }
63071a271a75SMatthew G. Knepley 
6308d71ae5a4SJacob 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[])
6309d71ae5a4SJacob Faibussowitsch {
63101a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
63111a271a75SMatthew G. Knepley 
63121a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6313fe02ba77SJed Brown   *size = 0;
63141a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
631597e99dd9SToby Isaac     PetscInt            p;
631697e99dd9SToby Isaac     const PetscInt    **perms = NULL;
631797e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63181a271a75SMatthew G. Knepley 
63199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
632097e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
632197e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
632297e99dd9SToby Isaac       PetscInt           fdof, foff, b;
63231a271a75SMatthew G. Knepley       const PetscScalar *varr;
632497e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
632597e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
63261a271a75SMatthew G. Knepley 
63279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63291a271a75SMatthew G. Knepley       varr = &vArray[foff];
633097e99dd9SToby Isaac       if (clperm) {
63319371c9d4SSatish Balay         if (perm) {
6332ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
63331a271a75SMatthew G. Knepley         } else {
6334ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
63359371c9d4SSatish Balay         }
63369371c9d4SSatish Balay         if (flip) {
6337ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
63389371c9d4SSatish Balay         }
63399371c9d4SSatish Balay       } else {
63409371c9d4SSatish Balay         if (perm) {
6341ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
63429371c9d4SSatish Balay         } else {
6343ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
63449371c9d4SSatish Balay         }
63459371c9d4SSatish Balay         if (flip) {
6346ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
63479371c9d4SSatish Balay         }
63481a271a75SMatthew G. Knepley       }
634997e99dd9SToby Isaac       offset += fdof;
63501a271a75SMatthew G. Knepley     }
63519566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
63521a271a75SMatthew G. Knepley   }
63531a271a75SMatthew G. Knepley   *size = offset;
63543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63551a271a75SMatthew G. Knepley }
63561a271a75SMatthew G. Knepley 
6357e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
635807218a29SMatthew G. Knepley {
635907218a29SMatthew G. Knepley   PetscSection    clSection;
636007218a29SMatthew G. Knepley   IS              clPoints;
636107218a29SMatthew G. Knepley   PetscInt       *points = NULL;
6362e8e188d2SZach Atkins   const PetscInt *clp, *perm = NULL;
636307218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
636407218a29SMatthew G. Knepley 
636507218a29SMatthew G. Knepley   PetscFunctionBeginHot;
636607218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
636707218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
636807218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6369e8e188d2SZach Atkins   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
637007218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
637107218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
637207218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
637307218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
637407218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
637507218a29SMatthew G. Knepley   }
637607218a29SMatthew G. Knepley   /* Get points */
637707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
637807218a29SMatthew G. Knepley   /* Get sizes */
637907218a29SMatthew G. Knepley   asize = 0;
638007218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
638107218a29SMatthew G. Knepley     PetscInt dof;
638207218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
638307218a29SMatthew G. Knepley     asize += dof;
638407218a29SMatthew G. Knepley   }
638507218a29SMatthew G. Knepley   if (values) {
638607218a29SMatthew G. Knepley     const PetscScalar *vArray;
638707218a29SMatthew G. Knepley     PetscInt           size;
638807218a29SMatthew G. Knepley 
638907218a29SMatthew G. Knepley     if (*values) {
639007218a29SMatthew 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);
639107218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
6392e8e188d2SZach Atkins     if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
639307218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
639407218a29SMatthew G. Knepley     /* Get values */
639507218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
639607218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
639707218a29SMatthew 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);
639807218a29SMatthew G. Knepley     /* Cleanup array */
639907218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
640007218a29SMatthew G. Knepley   }
640107218a29SMatthew G. Knepley   if (csize) *csize = asize;
640207218a29SMatthew G. Knepley   /* Cleanup points */
640307218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
640407218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
640507218a29SMatthew G. Knepley }
640607218a29SMatthew G. Knepley 
6407552f7358SJed Brown /*@C
6408552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6409552f7358SJed Brown 
6410552f7358SJed Brown   Not collective
6411552f7358SJed Brown 
6412552f7358SJed Brown   Input Parameters:
6413a1cb98faSBarry Smith + dm      - The `DM`
641420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6415552f7358SJed Brown . v       - The local vector
6416a1cb98faSBarry Smith - point   - The point in the `DM`
6417552f7358SJed Brown 
64186b867d5aSJose E. Roman   Input/Output Parameters:
641920f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
642020f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
642120f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
642222c1ee49SMatthew G. Knepley 
6423552f7358SJed Brown   Level: intermediate
6424552f7358SJed Brown 
6425a1cb98faSBarry Smith   Notes:
642620f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6427a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6428a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6429a1cb98faSBarry Smith 
6430a1cb98faSBarry Smith   A typical use could be
6431a1cb98faSBarry Smith .vb
6432a1cb98faSBarry Smith    values = NULL;
6433a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6434a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6435a1cb98faSBarry Smith      <Compute on closure>
6436a1cb98faSBarry Smith    }
6437a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6438a1cb98faSBarry Smith .ve
6439a1cb98faSBarry Smith   or
6440a1cb98faSBarry Smith .vb
6441a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6442a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6443a1cb98faSBarry Smith      clSize = clMaxSize;
6444a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6445a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6446a1cb98faSBarry Smith        <Compute on closure>
6447a1cb98faSBarry Smith      }
6448a1cb98faSBarry Smith    }
6449a1cb98faSBarry Smith    PetscFree(values);
6450a1cb98faSBarry Smith .ve
6451a1cb98faSBarry Smith 
645260225df5SJacob Faibussowitsch   Fortran Notes:
645320f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6454a1cb98faSBarry Smith 
64551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6456552f7358SJed Brown @*/
6457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6458d71ae5a4SJacob Faibussowitsch {
6459d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6460e8e188d2SZach Atkins   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values));
64613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6462552f7358SJed Brown }
6463552f7358SJed Brown 
6464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6465d71ae5a4SJacob Faibussowitsch {
6466e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6467e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6468e5c487bfSMatthew G. Knepley   IS                 clPoints;
6469e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6470e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6471e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6472c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6473c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6474e5c487bfSMatthew G. Knepley 
6475e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6476e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64779566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6478e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6479e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
64819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
64829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6483e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
64849566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
64853ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6486e5c487bfSMatthew G. Knepley   }
6487e5c487bfSMatthew G. Knepley   /* Get points */
648807218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6489c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6490c459fbc1SJed Brown     PetscInt dof;
64919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6492c459fbc1SJed Brown     clsize += dof;
6493c459fbc1SJed Brown   }
64949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6495e5c487bfSMatthew G. Knepley   /* Filter points */
6496e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6497e5c487bfSMatthew G. Knepley     PetscInt dep;
6498e5c487bfSMatthew G. Knepley 
64999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6500e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6501e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6502e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6503e5c487bfSMatthew G. Knepley     ++Np;
6504e5c487bfSMatthew G. Knepley   }
6505e5c487bfSMatthew G. Knepley   /* Get array */
6506e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6507e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6508e5c487bfSMatthew G. Knepley 
6509e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
65109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6511e5c487bfSMatthew G. Knepley       asize += dof;
6512e5c487bfSMatthew G. Knepley     }
6513e5c487bfSMatthew G. Knepley     if (!values) {
65149566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6515e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
65163ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6517e5c487bfSMatthew G. Knepley     }
65189566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6519e5c487bfSMatthew G. Knepley   } else {
6520e5c487bfSMatthew G. Knepley     array = *values;
6521e5c487bfSMatthew G. Knepley   }
65229566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6523e5c487bfSMatthew G. Knepley   /* Get values */
65249566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
65259566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6526e5c487bfSMatthew G. Knepley   /* Cleanup points */
65279566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6528e5c487bfSMatthew G. Knepley   /* Cleanup array */
65299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6530e5c487bfSMatthew G. Knepley   if (!*values) {
6531e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6532e5c487bfSMatthew G. Knepley     *values = array;
6533e5c487bfSMatthew G. Knepley   } else {
653463a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6535e5c487bfSMatthew G. Knepley     *csize = size;
6536e5c487bfSMatthew G. Knepley   }
65373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6538e5c487bfSMatthew G. Knepley }
6539e5c487bfSMatthew G. Knepley 
6540552f7358SJed Brown /*@C
6541552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6542552f7358SJed Brown 
6543552f7358SJed Brown   Not collective
6544552f7358SJed Brown 
6545552f7358SJed Brown   Input Parameters:
6546a1cb98faSBarry Smith + dm      - The `DM`
654720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6548552f7358SJed Brown . v       - The local vector
6549a1cb98faSBarry Smith . point   - The point in the `DM`
655020f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6551552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6552552f7358SJed Brown 
6553552f7358SJed Brown   Level: intermediate
6554552f7358SJed Brown 
6555a1cb98faSBarry Smith   Note:
655620f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6557a1cb98faSBarry Smith 
655860225df5SJacob Faibussowitsch   Fortran Notes:
655920f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6560a1cb98faSBarry Smith 
65611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6562552f7358SJed Brown @*/
6563d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6564d71ae5a4SJacob Faibussowitsch {
6565552f7358SJed Brown   PetscInt size = 0;
6566552f7358SJed Brown 
6567552f7358SJed Brown   PetscFunctionBegin;
6568552f7358SJed Brown   /* Should work without recalculating size */
65699566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6570c9fdaa05SMatthew G. Knepley   *values = NULL;
65713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6572552f7358SJed Brown }
6573552f7358SJed Brown 
6574d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6575d71ae5a4SJacob Faibussowitsch {
65769371c9d4SSatish Balay   *x += y;
65779371c9d4SSatish Balay }
6578d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6579d71ae5a4SJacob Faibussowitsch {
65809371c9d4SSatish Balay   *x = y;
65819371c9d4SSatish Balay }
6582552f7358SJed Brown 
6583d71ae5a4SJacob 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[])
6584d71ae5a4SJacob Faibussowitsch {
6585552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6586552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6587552f7358SJed Brown   PetscScalar    *a;
6588552f7358SJed Brown   PetscInt        off, cind = 0, k;
6589552f7358SJed Brown 
6590552f7358SJed Brown   PetscFunctionBegin;
65919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
65929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6593552f7358SJed Brown   a = &array[off];
6594552f7358SJed Brown   if (!cdof || setBC) {
659597e99dd9SToby Isaac     if (clperm) {
65969371c9d4SSatish Balay       if (perm) {
6597ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6598552f7358SJed Brown       } else {
6599ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
66009371c9d4SSatish Balay       }
66019371c9d4SSatish Balay     } else {
66029371c9d4SSatish Balay       if (perm) {
6603ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
66049371c9d4SSatish Balay       } else {
6605ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
66069371c9d4SSatish Balay       }
6607552f7358SJed Brown     }
6608552f7358SJed Brown   } else {
66099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
661097e99dd9SToby Isaac     if (clperm) {
66119371c9d4SSatish Balay       if (perm) {
66129371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
66139371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66149371c9d4SSatish Balay             ++cind;
66159371c9d4SSatish Balay             continue;
66169371c9d4SSatish Balay           }
661797e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6618552f7358SJed Brown         }
6619552f7358SJed Brown       } else {
6620552f7358SJed Brown         for (k = 0; k < dof; ++k) {
66219371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66229371c9d4SSatish Balay             ++cind;
66239371c9d4SSatish Balay             continue;
66249371c9d4SSatish Balay           }
662597e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
662697e99dd9SToby Isaac         }
662797e99dd9SToby Isaac       }
662897e99dd9SToby Isaac     } else {
662997e99dd9SToby Isaac       if (perm) {
663097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66319371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66329371c9d4SSatish Balay             ++cind;
66339371c9d4SSatish Balay             continue;
66349371c9d4SSatish Balay           }
663597e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
663697e99dd9SToby Isaac         }
663797e99dd9SToby Isaac       } else {
663897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66399371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66409371c9d4SSatish Balay             ++cind;
66419371c9d4SSatish Balay             continue;
66429371c9d4SSatish Balay           }
664397e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
664497e99dd9SToby Isaac         }
6645552f7358SJed Brown       }
6646552f7358SJed Brown     }
6647552f7358SJed Brown   }
66483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6649552f7358SJed Brown }
6650552f7358SJed Brown 
6651d71ae5a4SJacob 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[])
6652d71ae5a4SJacob Faibussowitsch {
6653a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6654a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6655a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6656a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6657a5e93ea8SMatthew G. Knepley 
6658a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
66599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
66609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6661a5e93ea8SMatthew G. Knepley   a = &array[off];
6662a5e93ea8SMatthew G. Knepley   if (cdof) {
66639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
666497e99dd9SToby Isaac     if (clperm) {
666597e99dd9SToby Isaac       if (perm) {
6666a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6667a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
666897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
666997e99dd9SToby Isaac             cind++;
6670a5e93ea8SMatthew G. Knepley           }
6671a5e93ea8SMatthew G. Knepley         }
6672a5e93ea8SMatthew G. Knepley       } else {
6673a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6674a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
667597e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
667697e99dd9SToby Isaac             cind++;
667797e99dd9SToby Isaac           }
667897e99dd9SToby Isaac         }
667997e99dd9SToby Isaac       }
668097e99dd9SToby Isaac     } else {
668197e99dd9SToby Isaac       if (perm) {
668297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
668497e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
668597e99dd9SToby Isaac             cind++;
668697e99dd9SToby Isaac           }
668797e99dd9SToby Isaac         }
668897e99dd9SToby Isaac       } else {
668997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
669097e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
669197e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
669297e99dd9SToby Isaac             cind++;
669397e99dd9SToby Isaac           }
6694a5e93ea8SMatthew G. Knepley         }
6695a5e93ea8SMatthew G. Knepley       }
6696a5e93ea8SMatthew G. Knepley     }
6697a5e93ea8SMatthew G. Knepley   }
66983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6699a5e93ea8SMatthew G. Knepley }
6700a5e93ea8SMatthew G. Knepley 
6701d71ae5a4SJacob 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[])
6702d71ae5a4SJacob Faibussowitsch {
6703552f7358SJed Brown   PetscScalar    *a;
67041a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67051a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
670697e99dd9SToby Isaac   PetscInt        cind = 0, b;
6707552f7358SJed Brown 
6708552f7358SJed Brown   PetscFunctionBegin;
67099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67121a271a75SMatthew G. Knepley   a = &array[foff];
6713552f7358SJed Brown   if (!fcdof || setBC) {
671497e99dd9SToby Isaac     if (clperm) {
67159371c9d4SSatish Balay       if (perm) {
6716ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6717552f7358SJed Brown       } else {
6718ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
67199371c9d4SSatish Balay       }
67209371c9d4SSatish Balay     } else {
67219371c9d4SSatish Balay       if (perm) {
6722ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
67239371c9d4SSatish Balay       } else {
6724ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
67259371c9d4SSatish Balay       }
6726552f7358SJed Brown     }
6727552f7358SJed Brown   } else {
67289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
672997e99dd9SToby Isaac     if (clperm) {
673097e99dd9SToby Isaac       if (perm) {
673197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67329371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67339371c9d4SSatish Balay             ++cind;
67349371c9d4SSatish Balay             continue;
67359371c9d4SSatish Balay           }
673697e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6737552f7358SJed Brown         }
6738552f7358SJed Brown       } else {
673997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67409371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67419371c9d4SSatish Balay             ++cind;
67429371c9d4SSatish Balay             continue;
67439371c9d4SSatish Balay           }
674497e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
674597e99dd9SToby Isaac         }
674697e99dd9SToby Isaac       }
674797e99dd9SToby Isaac     } else {
674897e99dd9SToby Isaac       if (perm) {
674997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67509371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67519371c9d4SSatish Balay             ++cind;
67529371c9d4SSatish Balay             continue;
67539371c9d4SSatish Balay           }
675497e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
675597e99dd9SToby Isaac         }
675697e99dd9SToby Isaac       } else {
675797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67589371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67599371c9d4SSatish Balay             ++cind;
67609371c9d4SSatish Balay             continue;
67619371c9d4SSatish Balay           }
676297e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6763552f7358SJed Brown         }
6764552f7358SJed Brown       }
6765552f7358SJed Brown     }
6766552f7358SJed Brown   }
67671a271a75SMatthew G. Knepley   *offset += fdof;
67683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6769552f7358SJed Brown }
6770552f7358SJed Brown 
6771d71ae5a4SJacob 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[])
6772d71ae5a4SJacob Faibussowitsch {
6773a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
67741a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67751a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67765da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6777ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6778a5e93ea8SMatthew G. Knepley 
6779a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
67809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
67819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67841a271a75SMatthew G. Knepley   a = &array[foff];
6785a5e93ea8SMatthew G. Knepley   if (fcdof) {
6786ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
67879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
678897e99dd9SToby Isaac     if (clperm) {
678997e99dd9SToby Isaac       if (perm) {
6790ba322698SMatthew G. Knepley         if (comps) {
6791ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6792ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67939371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67949371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67959371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67969371c9d4SSatish Balay             }
67979371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67989371c9d4SSatish Balay               ++cind;
67999371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68009371c9d4SSatish Balay             }
6801ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6802ba322698SMatthew G. Knepley           }
6803ba322698SMatthew G. Knepley         } else {
680497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
680597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
680697e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6807a5e93ea8SMatthew G. Knepley               ++cind;
6808a5e93ea8SMatthew G. Knepley             }
6809a5e93ea8SMatthew G. Knepley           }
6810ba322698SMatthew G. Knepley         }
6811ba322698SMatthew G. Knepley       } else {
6812ba322698SMatthew G. Knepley         if (comps) {
6813ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6814ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68159371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68169371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68179371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68189371c9d4SSatish Balay             }
68199371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68209371c9d4SSatish Balay               ++cind;
68219371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68229371c9d4SSatish Balay             }
6823ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6824ba322698SMatthew G. Knepley           }
6825a5e93ea8SMatthew G. Knepley         } else {
682697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
682797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
682897e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
682997e99dd9SToby Isaac               ++cind;
683097e99dd9SToby Isaac             }
683197e99dd9SToby Isaac           }
683297e99dd9SToby Isaac         }
6833ba322698SMatthew G. Knepley       }
683497e99dd9SToby Isaac     } else {
683597e99dd9SToby Isaac       if (perm) {
6836ba322698SMatthew G. Knepley         if (comps) {
6837ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6838ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68399371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68409371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68419371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68429371c9d4SSatish Balay             }
68439371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68449371c9d4SSatish Balay               ++cind;
68459371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68469371c9d4SSatish Balay             }
6847ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6848ba322698SMatthew G. Knepley           }
6849ba322698SMatthew G. Knepley         } else {
685097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
685197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
685297e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
685397e99dd9SToby Isaac               ++cind;
685497e99dd9SToby Isaac             }
685597e99dd9SToby Isaac           }
6856ba322698SMatthew G. Knepley         }
6857ba322698SMatthew G. Knepley       } else {
6858ba322698SMatthew G. Knepley         if (comps) {
6859ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6860ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68619371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68629371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68639371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68649371c9d4SSatish Balay             }
68659371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68669371c9d4SSatish Balay               ++cind;
68679371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68689371c9d4SSatish Balay             }
6869ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6870ba322698SMatthew G. Knepley           }
687197e99dd9SToby Isaac         } else {
687297e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
687397e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
687497e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6875a5e93ea8SMatthew G. Knepley               ++cind;
6876a5e93ea8SMatthew G. Knepley             }
6877a5e93ea8SMatthew G. Knepley           }
6878a5e93ea8SMatthew G. Knepley         }
6879a5e93ea8SMatthew G. Knepley       }
6880a5e93ea8SMatthew G. Knepley     }
6881ba322698SMatthew G. Knepley   }
68821a271a75SMatthew G. Knepley   *offset += fdof;
68833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6884a5e93ea8SMatthew G. Knepley }
6885a5e93ea8SMatthew G. Knepley 
6886d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6887d71ae5a4SJacob Faibussowitsch {
6888552f7358SJed Brown   PetscScalar    *array;
68891b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
68901b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6891552f7358SJed Brown 
68921b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
68939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
68949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
68959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
68969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
68979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6898b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6899b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6900b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6901b6ebb6e6SMatthew G. Knepley 
69029371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
69039371c9d4SSatish Balay       dof = 0;
69049371c9d4SSatish Balay       continue;
69059371c9d4SSatish Balay     }
69069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6907b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6908b6ebb6e6SMatthew G. Knepley     {
6909b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6910b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6911b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6912b6ebb6e6SMatthew G. Knepley 
69139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
69149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6915b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6916b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6917b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6918ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6919b6ebb6e6SMatthew G. Knepley         } else {
6920ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6921b6ebb6e6SMatthew G. Knepley         }
6922b6ebb6e6SMatthew G. Knepley       } else {
69239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6924b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6925b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69269371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69279371c9d4SSatish Balay               ++cind;
69289371c9d4SSatish Balay               continue;
69299371c9d4SSatish Balay             }
6930b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6931b6ebb6e6SMatthew G. Knepley           }
6932b6ebb6e6SMatthew G. Knepley         } else {
6933b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69349371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69359371c9d4SSatish Balay               ++cind;
69369371c9d4SSatish Balay               continue;
69379371c9d4SSatish Balay             }
6938b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6939b6ebb6e6SMatthew G. Knepley           }
6940b6ebb6e6SMatthew G. Knepley         }
6941b6ebb6e6SMatthew G. Knepley       }
6942b6ebb6e6SMatthew G. Knepley     }
6943b6ebb6e6SMatthew G. Knepley   }
69449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6946b6ebb6e6SMatthew G. Knepley }
69471b406b76SMatthew G. Knepley 
69481b406b76SMatthew G. Knepley /*@C
694920f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
69501b406b76SMatthew G. Knepley 
69511b406b76SMatthew G. Knepley   Not collective
69521b406b76SMatthew G. Knepley 
69531b406b76SMatthew G. Knepley   Input Parameters:
6954a1cb98faSBarry Smith + dm      - The `DM`
695520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
69561b406b76SMatthew G. Knepley . v       - The local vector
695720f4b53cSBarry Smith . point   - The point in the `DM`
69581b406b76SMatthew G. Knepley . values  - The array of values
6959a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6960a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
69611b406b76SMatthew G. Knepley 
69621b406b76SMatthew G. Knepley   Level: intermediate
69631b406b76SMatthew G. Knepley 
69641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
69651b406b76SMatthew G. Knepley @*/
6966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6967d71ae5a4SJacob Faibussowitsch {
69681b406b76SMatthew G. Knepley   PetscSection    clSection;
69691b406b76SMatthew G. Knepley   IS              clPoints;
69701b406b76SMatthew G. Knepley   PetscScalar    *array;
69711b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
697227f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6973c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
69741b406b76SMatthew G. Knepley 
69751a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
69761b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69779566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
69781a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
69791a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
69809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
69819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
69821b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
69839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
69843ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
69851b406b76SMatthew G. Knepley   }
69861a271a75SMatthew G. Knepley   /* Get points */
698707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6988c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6989c459fbc1SJed Brown     PetscInt dof;
69909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6991c459fbc1SJed Brown     clsize += dof;
6992c459fbc1SJed Brown   }
69939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
69941a271a75SMatthew G. Knepley   /* Get array */
69959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
69961a271a75SMatthew G. Knepley   /* Get values */
6997ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
699897e99dd9SToby Isaac     PetscInt offset = 0, f;
6999552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
700097e99dd9SToby Isaac       const PetscInt    **perms = NULL;
700197e99dd9SToby Isaac       const PetscScalar **flips = NULL;
700297e99dd9SToby Isaac 
70039566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7004552f7358SJed Brown       switch (mode) {
7005552f7358SJed Brown       case INSERT_VALUES:
700697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
700797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
700897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
700997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70103ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
70119371c9d4SSatish Balay         }
70129371c9d4SSatish Balay         break;
7013552f7358SJed Brown       case INSERT_ALL_VALUES:
701497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
701597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
701697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
701797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70183ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
70199371c9d4SSatish Balay         }
70209371c9d4SSatish Balay         break;
7021a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
702297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
702397e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
702497e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
702597e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70263ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
70279371c9d4SSatish Balay         }
70289371c9d4SSatish Balay         break;
7029552f7358SJed Brown       case ADD_VALUES:
703097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
703397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70343ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
70359371c9d4SSatish Balay         }
70369371c9d4SSatish Balay         break;
7037552f7358SJed Brown       case ADD_ALL_VALUES:
703897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
704097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70423ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
70439371c9d4SSatish Balay         }
70449371c9d4SSatish Balay         break;
7045304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
704697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
704797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
704897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70503ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
70519371c9d4SSatish Balay         }
70529371c9d4SSatish Balay         break;
7053d71ae5a4SJacob Faibussowitsch       default:
7054d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7055552f7358SJed Brown       }
70569566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
70571a271a75SMatthew G. Knepley     }
7058552f7358SJed Brown   } else {
70591a271a75SMatthew G. Knepley     PetscInt            dof, off;
706097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
706197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
70621a271a75SMatthew G. Knepley 
70639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
7064552f7358SJed Brown     switch (mode) {
7065552f7358SJed Brown     case INSERT_VALUES:
706697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
706797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
706897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
706997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70713ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
70729371c9d4SSatish Balay       }
70739371c9d4SSatish Balay       break;
7074552f7358SJed Brown     case INSERT_ALL_VALUES:
707597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
707697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
707797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
707897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70803ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
70819371c9d4SSatish Balay       }
70829371c9d4SSatish Balay       break;
7083a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
708497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
708597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
708797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70893ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
70909371c9d4SSatish Balay       }
70919371c9d4SSatish Balay       break;
7092552f7358SJed Brown     case ADD_VALUES:
709397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
709497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
709597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70979566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70983ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
70999371c9d4SSatish Balay       }
71009371c9d4SSatish Balay       break;
7101552f7358SJed Brown     case ADD_ALL_VALUES:
710297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
710397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
710497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
710597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71073ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
71089371c9d4SSatish Balay       }
71099371c9d4SSatish Balay       break;
7110304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
711197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
711297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
711397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
711497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71159566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71163ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
71179371c9d4SSatish Balay       }
71189371c9d4SSatish Balay       break;
7119d71ae5a4SJacob Faibussowitsch     default:
7120d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7121552f7358SJed Brown     }
71229566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
7123552f7358SJed Brown   }
71241a271a75SMatthew G. Knepley   /* Cleanup points */
71259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
71261a271a75SMatthew G. Knepley   /* Cleanup array */
71279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
71283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7129552f7358SJed Brown }
7130552f7358SJed Brown 
71315f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
7132d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
7133d71ae5a4SJacob Faibussowitsch {
71345f790a90SMatthew G. Knepley   PetscFunctionBegin;
713511cc89d2SBarry Smith   *contains = PETSC_TRUE;
71365f790a90SMatthew G. Knepley   if (label) {
7137d6177c40SToby Isaac     PetscInt fdof;
71385f790a90SMatthew G. Knepley 
713911cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
714011cc89d2SBarry Smith     if (!*contains) {
71419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71425f790a90SMatthew G. Knepley       *offset += fdof;
71433ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
71445f790a90SMatthew G. Knepley     }
71455f790a90SMatthew G. Knepley   }
71463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71475f790a90SMatthew G. Knepley }
71485f790a90SMatthew G. Knepley 
714997529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
7150d71ae5a4SJacob 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)
7151d71ae5a4SJacob Faibussowitsch {
7152e07394fbSMatthew G. Knepley   PetscSection    clSection;
7153e07394fbSMatthew G. Knepley   IS              clPoints;
7154e07394fbSMatthew G. Knepley   PetscScalar    *array;
7155e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
715697529cf3SJed Brown   const PetscInt *clp;
7157e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
715897e99dd9SToby Isaac   PetscInt        offset = 0, f;
7159e07394fbSMatthew G. Knepley 
7160e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
7161e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71629566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
7163e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7164e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
71659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7166e07394fbSMatthew G. Knepley   /* Get points */
716707218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
7168e07394fbSMatthew G. Knepley   /* Get array */
71699566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
7170e07394fbSMatthew G. Knepley   /* Get values */
7171e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
717297e99dd9SToby Isaac     const PetscInt    **perms = NULL;
717397e99dd9SToby Isaac     const PetscScalar **flips = NULL;
717411cc89d2SBarry Smith     PetscBool           contains;
717597e99dd9SToby Isaac 
7176e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
7177e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
7178e07394fbSMatthew G. Knepley         PetscInt fdof;
71799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
7180e07394fbSMatthew G. Knepley         offset += fdof;
7181e07394fbSMatthew G. Knepley       }
7182e07394fbSMatthew G. Knepley       continue;
7183e07394fbSMatthew G. Knepley     }
71849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7185e07394fbSMatthew G. Knepley     switch (mode) {
7186e07394fbSMatthew G. Knepley     case INSERT_VALUES:
718797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
718897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
718997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
719097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
719111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
719211cc89d2SBarry Smith         if (!contains) continue;
71939566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
71949371c9d4SSatish Balay       }
71959371c9d4SSatish Balay       break;
7196e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
719797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
719897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
719997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
720097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
720111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
720211cc89d2SBarry Smith         if (!contains) continue;
72039566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
72049371c9d4SSatish Balay       }
72059371c9d4SSatish Balay       break;
7206e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
720797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
720897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
720997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
721097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
721111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
721211cc89d2SBarry Smith         if (!contains) continue;
72139566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
72149371c9d4SSatish Balay       }
72159371c9d4SSatish Balay       break;
7216e07394fbSMatthew G. Knepley     case ADD_VALUES:
721797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
721897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
721997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
722097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
722111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
722211cc89d2SBarry Smith         if (!contains) continue;
72239566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
72249371c9d4SSatish Balay       }
72259371c9d4SSatish Balay       break;
7226e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
722797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
722897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
722997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
723097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
723111cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
723211cc89d2SBarry Smith         if (!contains) continue;
72339566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
72349371c9d4SSatish Balay       }
72359371c9d4SSatish Balay       break;
7236d71ae5a4SJacob Faibussowitsch     default:
7237d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7238e07394fbSMatthew G. Knepley     }
72399566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7240e07394fbSMatthew G. Knepley   }
7241e07394fbSMatthew G. Knepley   /* Cleanup points */
72429566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
7243e07394fbSMatthew G. Knepley   /* Cleanup array */
72449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
72453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7246e07394fbSMatthew G. Knepley }
7247e07394fbSMatthew G. Knepley 
7248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
7249d71ae5a4SJacob Faibussowitsch {
7250552f7358SJed Brown   PetscMPIInt rank;
7251552f7358SJed Brown   PetscInt    i, j;
7252552f7358SJed Brown 
7253552f7358SJed Brown   PetscFunctionBegin;
72549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
725563a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
725663a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
725763a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
7258b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
72593ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
7260b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
72619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
7262b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
7263519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
72649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
7265552f7358SJed Brown #else
72669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
7267552f7358SJed Brown #endif
7268552f7358SJed Brown     }
72699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7270552f7358SJed Brown   }
72713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7272552f7358SJed Brown }
7273552f7358SJed Brown 
727405586334SMatthew G. Knepley /*
727505586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
727605586334SMatthew G. Knepley 
727705586334SMatthew G. Knepley   Input Parameters:
727805586334SMatthew G. Knepley + section - The section for this data layout
727936fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
728005586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
728105586334SMatthew G. Knepley . off     - The global offset of this point
728205586334SMatthew G. Knepley . loff    - The local offset of each field
7283a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
728405586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
728505586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
728605586334SMatthew G. Knepley 
728705586334SMatthew G. Knepley   Output Parameter:
728805586334SMatthew G. Knepley . indices - Indices for dofs on this point
728905586334SMatthew G. Knepley 
729005586334SMatthew G. Knepley   Level: developer
729105586334SMatthew G. Knepley 
729205586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
729305586334SMatthew G. Knepley */
7294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
7295d71ae5a4SJacob Faibussowitsch {
7296e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
7297552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7298552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7299552f7358SJed Brown   PetscInt        cind = 0, k;
7300552f7358SJed Brown 
7301552f7358SJed Brown   PetscFunctionBegin;
730208401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
73049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
7305552f7358SJed Brown   if (!cdof || setBC) {
730605586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
730705586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
730805586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
730905586334SMatthew G. Knepley 
731005586334SMatthew G. Knepley       indices[ind] = off + k;
7311552f7358SJed Brown     }
7312552f7358SJed Brown   } else {
73139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
73144acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
731505586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
731605586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
731705586334SMatthew G. Knepley 
73184acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
73194acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
732005586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
73214acb8e1eSToby Isaac         ++cind;
73224acb8e1eSToby Isaac       } else {
732336fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7324552f7358SJed Brown       }
7325552f7358SJed Brown     }
7326552f7358SJed Brown   }
7327e6ccafaeSMatthew G Knepley   *loff += dof;
73283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7329552f7358SJed Brown }
7330552f7358SJed Brown 
73317e29afd2SMatthew G. Knepley /*
733236fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
73337e29afd2SMatthew G. Knepley 
733436fa2b79SJed Brown  Input Parameters:
733536fa2b79SJed Brown + section - a section (global or local)
733620f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
733736fa2b79SJed Brown . point - point within section
733836fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
733936fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
734036fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
734136fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
734236fa2b79SJed Brown . permsoff - offset
734336fa2b79SJed Brown - indperm - index permutation
734436fa2b79SJed Brown 
734536fa2b79SJed Brown  Output Parameter:
734636fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
734736fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
734836fa2b79SJed Brown 
734936fa2b79SJed Brown  Notes:
735036fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
735136fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
735236fa2b79SJed Brown  in the local vector.
735336fa2b79SJed Brown 
735436fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
735536fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
735636fa2b79SJed Brown 
735736fa2b79SJed Brown  Developer Note:
735836fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
735936fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
736036fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
736136fa2b79SJed Brown 
736236fa2b79SJed Brown  Example:
736336fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
736436fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
736536fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
736636fa2b79SJed 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.
736736fa2b79SJed Brown 
736836fa2b79SJed Brown  Level: developer
73697e29afd2SMatthew G. Knepley */
7370d71ae5a4SJacob 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[])
7371d71ae5a4SJacob Faibussowitsch {
7372552f7358SJed Brown   PetscInt numFields, foff, f;
7373552f7358SJed Brown 
7374552f7358SJed Brown   PetscFunctionBegin;
737508401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7377552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
73784acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7379552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
73804acb8e1eSToby Isaac     PetscInt        cind = 0, b;
73814acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7382552f7358SJed Brown 
73839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
73849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7385552f7358SJed Brown     if (!cfdof || setBC) {
738605586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
738705586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
738805586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
738905586334SMatthew G. Knepley 
739005586334SMatthew G. Knepley         indices[ind] = off + foff + b;
739105586334SMatthew G. Knepley       }
7392552f7358SJed Brown     } else {
73939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
739405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
739505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
739605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
739705586334SMatthew G. Knepley 
73984acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
739905586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7400552f7358SJed Brown           ++cind;
7401552f7358SJed Brown         } else {
740236fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7403552f7358SJed Brown         }
7404552f7358SJed Brown       }
7405552f7358SJed Brown     }
740636fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7407552f7358SJed Brown     foffs[f] += fdof;
7408552f7358SJed Brown   }
74093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7410552f7358SJed Brown }
7411552f7358SJed Brown 
74127e29afd2SMatthew G. Knepley /*
74137e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
74147e29afd2SMatthew G. Knepley 
74157e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7416645102dcSJed Brown 
7417645102dcSJed Brown  Notes:
7418645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7419645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
74207e29afd2SMatthew G. Knepley */
7421d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7422d71ae5a4SJacob Faibussowitsch {
74237e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
74247e29afd2SMatthew G. Knepley 
74257e29afd2SMatthew G. Knepley   PetscFunctionBegin;
74269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
74277e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
74287e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
74297e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
74307e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
74317e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
74327e29afd2SMatthew G. Knepley 
74339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
74349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
74359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7436645102dcSJed Brown     if (!cfdof) {
743705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
743805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
743905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
744005586334SMatthew G. Knepley 
744105586334SMatthew G. Knepley         indices[ind] = foff + b;
744205586334SMatthew G. Knepley       }
74437e29afd2SMatthew G. Knepley     } else {
74449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
744505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
744605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
744705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
744805586334SMatthew G. Knepley 
74497e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
745005586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
74517e29afd2SMatthew G. Knepley           ++cind;
74527e29afd2SMatthew G. Knepley         } else {
745305586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
74547e29afd2SMatthew G. Knepley         }
74557e29afd2SMatthew G. Knepley       }
74567e29afd2SMatthew G. Knepley     }
74577e29afd2SMatthew G. Knepley     foffs[f] += fdof;
74587e29afd2SMatthew G. Knepley   }
74593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74607e29afd2SMatthew G. Knepley }
74617e29afd2SMatthew G. Knepley 
7462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
7463d71ae5a4SJacob Faibussowitsch {
7464d3d1a6afSToby Isaac   Mat             cMat;
7465d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7466d3d1a6afSToby Isaac   IS              aIS;
7467d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7468d3d1a6afSToby Isaac   const PetscInt *anchors;
7469e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7470d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7471d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7472d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7473d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7474d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7475d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7476d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
74776ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7478d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7479d3d1a6afSToby Isaac 
7480d3d1a6afSToby Isaac   PetscFunctionBegin;
7481d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7482d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
74839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7484d3d1a6afSToby Isaac 
74859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7486d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7487d3d1a6afSToby Isaac   if (aSec) {
74889566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
74899566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
74909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7491d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7492d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7493d3d1a6afSToby Isaac      * into the global matrix anyway) */
7494d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7495d3d1a6afSToby Isaac       PetscInt b    = points[p];
74964b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7497d3d1a6afSToby Isaac 
74989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7499ad540459SPierre Jolivet       if (!bSecDof) continue;
750048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7501d3d1a6afSToby Isaac       if (bDof) {
7502d3d1a6afSToby Isaac         /* this point is constrained */
7503d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7504d3d1a6afSToby Isaac         PetscInt bOff, q;
7505d3d1a6afSToby Isaac 
7506d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7507d3d1a6afSToby Isaac         newNumPoints += bDof;
75089566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7509d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7510d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7511d3d1a6afSToby Isaac           PetscInt aDof;
7512d3d1a6afSToby Isaac 
75139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7514d3d1a6afSToby Isaac           newNumIndices += aDof;
7515d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7516d3d1a6afSToby Isaac             PetscInt fDof;
7517d3d1a6afSToby Isaac 
75189566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7519d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7520d3d1a6afSToby Isaac           }
7521d3d1a6afSToby Isaac         }
75229371c9d4SSatish Balay       } else {
7523d3d1a6afSToby Isaac         /* this point is not constrained */
7524d3d1a6afSToby Isaac         newNumPoints++;
75254b2f2278SToby Isaac         newNumIndices += bSecDof;
7526d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7527d3d1a6afSToby Isaac           PetscInt fDof;
7528d3d1a6afSToby Isaac 
75299566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7530d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7531d3d1a6afSToby Isaac         }
7532d3d1a6afSToby Isaac       }
7533d3d1a6afSToby Isaac     }
7534d3d1a6afSToby Isaac   }
7535d3d1a6afSToby Isaac   if (!anyConstrained) {
753672b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
753772b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
753872b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
753972b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
75409566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7542d3d1a6afSToby Isaac   }
7543d3d1a6afSToby Isaac 
75446ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
75456ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
75466ecaa68aSToby Isaac 
7547f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7548d3d1a6afSToby Isaac 
75496ecaa68aSToby Isaac   if (!outPoints && !outValues) {
75506ecaa68aSToby Isaac     if (offsets) {
7551ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
75526ecaa68aSToby Isaac     }
75539566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
75556ecaa68aSToby Isaac   }
75566ecaa68aSToby Isaac 
75571dca8a05SBarry 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);
7558d3d1a6afSToby Isaac 
75599566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7560d3d1a6afSToby Isaac 
7561d3d1a6afSToby Isaac   /* workspaces */
7562d3d1a6afSToby Isaac   if (numFields) {
7563d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75649566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75659566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7566d3d1a6afSToby Isaac     }
75679371c9d4SSatish Balay   } else {
75689566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75699566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7570d3d1a6afSToby Isaac   }
7571d3d1a6afSToby Isaac 
7572d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7573d3d1a6afSToby Isaac   if (numFields) {
75744b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
75754b2f2278SToby Isaac 
7576d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7577d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
75784b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7579d3d1a6afSToby Isaac 
75809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
75814b2f2278SToby Isaac       if (!bSecDof) {
75824b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
75834b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
75844b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
75854b2f2278SToby Isaac         }
75864b2f2278SToby Isaac         continue;
75874b2f2278SToby Isaac       }
758848a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7589d3d1a6afSToby Isaac       if (bDof) {
7590d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7591d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7592d3d1a6afSToby Isaac 
75939566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
75949566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7595d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7596d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7597d3d1a6afSToby Isaac             PetscInt aFDof;
7598d3d1a6afSToby Isaac 
75999566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7600d3d1a6afSToby Isaac             allFDof += aFDof;
7601d3d1a6afSToby Isaac           }
7602d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7603d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7604d3d1a6afSToby Isaac         }
76059371c9d4SSatish Balay       } else {
7606d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7607d3d1a6afSToby Isaac           PetscInt fDof;
7608d3d1a6afSToby Isaac 
76099566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7610d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7611d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7612d3d1a6afSToby Isaac         }
7613d3d1a6afSToby Isaac       }
7614d3d1a6afSToby Isaac     }
76154b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
76164b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
76174b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7618d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7619d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7620d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7621d3d1a6afSToby Isaac       }
762219f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
762319f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
76249566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7625d3d1a6afSToby Isaac     }
76269371c9d4SSatish Balay   } else {
7627d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7628d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
76294b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7630d3d1a6afSToby Isaac 
76319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
76324b2f2278SToby Isaac       if (!bSecDof) {
76334b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
76344b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
76354b2f2278SToby Isaac         continue;
76364b2f2278SToby Isaac       }
763748a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7638d3d1a6afSToby Isaac       if (bDof) {
76394b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7640d3d1a6afSToby Isaac 
76419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7642d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7643d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7644d3d1a6afSToby Isaac 
76459566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7646d3d1a6afSToby Isaac           allDof += aDof;
7647d3d1a6afSToby Isaac         }
7648d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
76494b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
76509371c9d4SSatish Balay       } else {
76514b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7652d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7653d3d1a6afSToby Isaac       }
7654d3d1a6afSToby Isaac     }
7655d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7656d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7657d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7658d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7659d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7660d3d1a6afSToby Isaac     }
76619566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7662d3d1a6afSToby Isaac   }
7663d3d1a6afSToby Isaac 
76646ecaa68aSToby Isaac   /* output arrays */
76659566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
76666ecaa68aSToby Isaac 
7667d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
76689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
76699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
76709566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
76719566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7672d3d1a6afSToby Isaac   if (numFields) {
7673d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7674d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7675d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
76764b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7677d3d1a6afSToby Isaac 
76789566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7679ad540459SPierre Jolivet       if (!bSecDof) continue;
768048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7681d3d1a6afSToby Isaac       if (bDof) {
7682d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7683d3d1a6afSToby Isaac 
7684d3d1a6afSToby Isaac         fStart[0] = 0;
7685d3d1a6afSToby Isaac         fEnd[0]   = 0;
7686d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7687d3d1a6afSToby Isaac           PetscInt fDof;
7688d3d1a6afSToby Isaac 
76899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7690d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7691d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7692d3d1a6afSToby Isaac         }
76939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
76949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7695d3d1a6afSToby Isaac 
7696d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7697d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7698d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7699d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7700d3d1a6afSToby Isaac 
7701d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7702d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7703d3d1a6afSToby Isaac         }
77049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7705d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7706d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7707d3d1a6afSToby Isaac 
7708d3d1a6afSToby Isaac           /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */
7709d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7710d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
77119566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
77129566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7713d3d1a6afSToby Isaac         }
7714d3d1a6afSToby Isaac         newP += bDof;
7715d3d1a6afSToby Isaac 
77166ecaa68aSToby Isaac         if (outValues) {
7717d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
771848a46eb9SPierre Jolivet           for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p]));
7719d3d1a6afSToby Isaac         }
77209371c9d4SSatish Balay       } else {
7721d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7722d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7723d3d1a6afSToby Isaac         newP++;
7724d3d1a6afSToby Isaac       }
7725d3d1a6afSToby Isaac     }
7726d3d1a6afSToby Isaac   } else {
7727d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7728d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7729d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
77304b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7731d3d1a6afSToby Isaac 
77329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7733ad540459SPierre Jolivet       if (!bSecDof) continue;
773448a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7735d3d1a6afSToby Isaac       if (bDof) {
7736d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7737d3d1a6afSToby Isaac 
77389566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
77399566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7740d3d1a6afSToby Isaac 
77419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7742d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7743d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7744d3d1a6afSToby Isaac 
7745d3d1a6afSToby Isaac           /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */
7746d3d1a6afSToby Isaac 
7747d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7748d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
77499566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
77509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7751d3d1a6afSToby Isaac         }
7752d3d1a6afSToby Isaac         newP += bDof;
7753d3d1a6afSToby Isaac 
7754d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
775548a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
77569371c9d4SSatish Balay       } else {
7757d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7758d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7759d3d1a6afSToby Isaac         newP++;
7760d3d1a6afSToby Isaac       }
7761d3d1a6afSToby Isaac     }
7762d3d1a6afSToby Isaac   }
7763d3d1a6afSToby Isaac 
77646ecaa68aSToby Isaac   if (outValues) {
77659566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
77669566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7767d3d1a6afSToby Isaac     /* multiply constraints on the right */
7768d3d1a6afSToby Isaac     if (numFields) {
7769d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7770d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7771d3d1a6afSToby Isaac 
7772d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7773d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7774d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7775d3d1a6afSToby Isaac           PetscInt c, r, k;
7776d3d1a6afSToby Isaac           PetscInt dof;
7777d3d1a6afSToby Isaac 
77789566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7779ad540459SPierre Jolivet           if (!dof) continue;
7780d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7781d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7782d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7783d3d1a6afSToby Isaac 
7784d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7785d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7786ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7787d3d1a6afSToby Isaac               }
7788d3d1a6afSToby Isaac             }
77899371c9d4SSatish Balay           } else {
7790d3d1a6afSToby Isaac             /* copy this column as is */
7791d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7792ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7793d3d1a6afSToby Isaac             }
7794d3d1a6afSToby Isaac           }
7795d3d1a6afSToby Isaac           oldOff += dof;
7796d3d1a6afSToby Isaac         }
7797d3d1a6afSToby Isaac       }
77989371c9d4SSatish Balay     } else {
7799d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7800d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7801d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7802d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7803d3d1a6afSToby Isaac         PetscInt c, r, k;
7804d3d1a6afSToby Isaac         PetscInt dof;
7805d3d1a6afSToby Isaac 
78069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7807ad540459SPierre Jolivet         if (!dof) continue;
7808d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7809d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7810d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7811d3d1a6afSToby Isaac 
7812d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7813d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7814ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7815d3d1a6afSToby Isaac             }
7816d3d1a6afSToby Isaac           }
78179371c9d4SSatish Balay         } else {
7818d3d1a6afSToby Isaac           /* copy this column as is */
7819d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7820ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7821d3d1a6afSToby Isaac           }
7822d3d1a6afSToby Isaac         }
7823d3d1a6afSToby Isaac         oldOff += dof;
7824d3d1a6afSToby Isaac       }
7825d3d1a6afSToby Isaac     }
7826d3d1a6afSToby Isaac 
78276ecaa68aSToby Isaac     if (multiplyLeft) {
78289566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
78299566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7830d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7831d3d1a6afSToby Isaac       if (numFields) {
7832d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7833d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7834d3d1a6afSToby Isaac 
7835d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7836d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7837d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7838d3d1a6afSToby Isaac             PetscInt c, r, k;
7839d3d1a6afSToby Isaac             PetscInt dof;
7840d3d1a6afSToby Isaac 
78419566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7842d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7843d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7844d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7845d3d1a6afSToby Isaac 
7846d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7847d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7848ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7849d3d1a6afSToby Isaac                 }
7850d3d1a6afSToby Isaac               }
78519371c9d4SSatish Balay             } else {
7852d3d1a6afSToby Isaac               /* copy this row as is */
7853d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7854ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7855d3d1a6afSToby Isaac               }
7856d3d1a6afSToby Isaac             }
7857d3d1a6afSToby Isaac             oldOff += dof;
7858d3d1a6afSToby Isaac           }
7859d3d1a6afSToby Isaac         }
78609371c9d4SSatish Balay       } else {
7861d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7862d3d1a6afSToby Isaac 
7863d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7864d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7865d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7866d3d1a6afSToby Isaac           PetscInt c, r, k;
7867d3d1a6afSToby Isaac           PetscInt dof;
7868d3d1a6afSToby Isaac 
78699566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7870d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7871d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7872d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7873d3d1a6afSToby Isaac 
7874d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7875d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7876ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7877d3d1a6afSToby Isaac               }
7878d3d1a6afSToby Isaac             }
78799371c9d4SSatish Balay           } else {
7880d3d1a6afSToby Isaac             /* copy this row as is */
78819fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7882ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7883d3d1a6afSToby Isaac             }
7884d3d1a6afSToby Isaac           }
7885d3d1a6afSToby Isaac           oldOff += dof;
7886d3d1a6afSToby Isaac         }
7887d3d1a6afSToby Isaac       }
7888d3d1a6afSToby Isaac 
78899566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
78909371c9d4SSatish Balay     } else {
78916ecaa68aSToby Isaac       newValues = tmpValues;
78926ecaa68aSToby Isaac     }
78936ecaa68aSToby Isaac   }
78946ecaa68aSToby Isaac 
7895d3d1a6afSToby Isaac   /* clean up */
78969566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
78979566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
78986ecaa68aSToby Isaac 
7899d3d1a6afSToby Isaac   if (numFields) {
7900d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
79019566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
79029566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
79039566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7904d3d1a6afSToby Isaac     }
79059371c9d4SSatish Balay   } else {
79069566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
79079566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
79089566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7909d3d1a6afSToby Isaac   }
79109566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7911d3d1a6afSToby Isaac 
7912d3d1a6afSToby Isaac   /* output */
79136ecaa68aSToby Isaac   if (outPoints) {
7914d3d1a6afSToby Isaac     *outPoints = newPoints;
79159371c9d4SSatish Balay   } else {
79169566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
79176ecaa68aSToby Isaac   }
7918ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7919ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
79203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7921d3d1a6afSToby Isaac }
7922d3d1a6afSToby Isaac 
79234a1e0b3eSMatthew G. Knepley /*@C
792471f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
79257cd05799SMatthew G. Knepley 
79267cd05799SMatthew G. Knepley   Not collective
79277cd05799SMatthew G. Knepley 
79287cd05799SMatthew G. Knepley   Input Parameters:
7929a1cb98faSBarry Smith + dm         - The `DM`
7930a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7931a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
793271f0bbf9SMatthew G. Knepley . point      - The point defining the closure
793371f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
79347cd05799SMatthew G. Knepley 
793571f0bbf9SMatthew G. Knepley   Output Parameters:
793671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
793771f0bbf9SMatthew G. Knepley . indices    - The dof indices
793820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
793920f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
79407cd05799SMatthew G. Knepley 
7941a1cb98faSBarry Smith   Level: advanced
794236fa2b79SJed Brown 
7943a1cb98faSBarry Smith   Notes:
7944a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7945a1cb98faSBarry Smith 
794620f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
794720f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
794836fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
794920f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
795036fa2b79SJed Brown   indices (with the above semantics) are implied.
79517cd05799SMatthew G. Knepley 
79521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7953a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
79544a1e0b3eSMatthew G. Knepley @*/
7955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7956d71ae5a4SJacob Faibussowitsch {
795771f0bbf9SMatthew G. Knepley   /* Closure ordering */
79587773e69fSMatthew G. Knepley   PetscSection    clSection;
79597773e69fSMatthew G. Knepley   IS              clPoints;
796071f0bbf9SMatthew G. Knepley   const PetscInt *clp;
796171f0bbf9SMatthew G. Knepley   PetscInt       *points;
796271f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
796371f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
79644acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
796571f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
796671f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
796771f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
796871f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
796971f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
797071f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
797171f0bbf9SMatthew G. Knepley 
797271f0bbf9SMatthew G. Knepley   PetscInt *idx;
797371f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
797471f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
79757773e69fSMatthew G. Knepley 
797671f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
79777773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79787773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
797936fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
79804f572ea9SToby Isaac   if (numIndices) PetscAssertPointer(numIndices, 6);
79814f572ea9SToby Isaac   if (indices) PetscAssertPointer(indices, 7);
79824f572ea9SToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 8);
79834f572ea9SToby Isaac   if (values) PetscAssertPointer(values, 9);
79849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
798563a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
79869566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
798771f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
798807218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7989c459fbc1SJed Brown   if (useClPerm) {
7990c459fbc1SJed Brown     PetscInt depth, clsize;
79919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7992c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7993c459fbc1SJed Brown       PetscInt dof;
79949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7995c459fbc1SJed Brown       clsize += dof;
7996c459fbc1SJed Brown     }
79979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7998c459fbc1SJed Brown   }
799971f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
800071f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
80017773e69fSMatthew G. Knepley     PetscInt dof, fdof;
80027773e69fSMatthew G. Knepley 
80039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
80047773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
80059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
80067773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
80077773e69fSMatthew G. Knepley     }
800871f0bbf9SMatthew G. Knepley     Ni += dof;
80097773e69fSMatthew G. Knepley   }
80107773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
80111dca8a05SBarry 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);
801271f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
801371f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
80149566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
80159566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
801671f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
801771f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
801871f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
80196ecaa68aSToby Isaac 
802071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
802171f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
802271f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
802371f0bbf9SMatthew G. Knepley 
80249566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
80259566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
802671f0bbf9SMatthew G. Knepley         if (flip) {
802771f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
802871f0bbf9SMatthew G. Knepley 
802971f0bbf9SMatthew G. Knepley           if (!valCopy) {
80309566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
803171f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
803271f0bbf9SMatthew G. Knepley             *values = valCopy;
803371f0bbf9SMatthew G. Knepley           }
803471f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
803571f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
803671f0bbf9SMatthew G. Knepley 
803771f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
803871f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
803971f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
80406ecaa68aSToby Isaac             }
80416ecaa68aSToby Isaac           }
804271f0bbf9SMatthew G. Knepley         }
804371f0bbf9SMatthew G. Knepley         foffset += fdof;
804471f0bbf9SMatthew G. Knepley       }
804571f0bbf9SMatthew G. Knepley     }
804671f0bbf9SMatthew G. Knepley   }
804771f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
80489566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
804971f0bbf9SMatthew G. Knepley   if (NclC) {
80509566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
805171f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
80529566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
80539566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
805471f0bbf9SMatthew G. Knepley     }
805571f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
80569566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
80579566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
805871f0bbf9SMatthew G. Knepley     }
80599566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
806071f0bbf9SMatthew G. Knepley     Ncl    = NclC;
806171f0bbf9SMatthew G. Knepley     Ni     = NiC;
806271f0bbf9SMatthew G. Knepley     points = pointsC;
806371f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
806471f0bbf9SMatthew G. Knepley   }
806571f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
80669566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
806771f0bbf9SMatthew G. Knepley   if (Nf) {
806871f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
806971f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
807071f0bbf9SMatthew G. Knepley 
80719371c9d4SSatish Balay     if (outOffsets) {
80729371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
80739371c9d4SSatish Balay     }
80749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
807571f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
807671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
807771f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
807871f0bbf9SMatthew G. Knepley 
80799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
80807773e69fSMatthew G. Knepley       }
80817773e69fSMatthew G. Knepley     } else {
808271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
808371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
808471f0bbf9SMatthew G. Knepley 
80859566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
808671f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
808771f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
808871f0bbf9SMatthew G. Knepley          * global section. */
80899566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
809071f0bbf9SMatthew G. Knepley       }
809171f0bbf9SMatthew G. Knepley     }
809271f0bbf9SMatthew G. Knepley   } else {
809371f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
809471f0bbf9SMatthew G. Knepley 
809571f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
809671f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
80974acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
80984acb8e1eSToby Isaac 
80999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
810071f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
810171f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
81029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
81037773e69fSMatthew G. Knepley     }
81047773e69fSMatthew G. Knepley   }
810571f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
810671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
81079566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
81089566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
81094acb8e1eSToby Isaac   }
811071f0bbf9SMatthew G. Knepley   if (NclC) {
81119566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
81127773e69fSMatthew G. Knepley   } else {
81139566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
81147773e69fSMatthew G. Knepley   }
811571f0bbf9SMatthew G. Knepley 
811671f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
811771f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
81183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81197773e69fSMatthew G. Knepley }
81207773e69fSMatthew G. Knepley 
81217cd05799SMatthew G. Knepley /*@C
812271f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
81237cd05799SMatthew G. Knepley 
81247cd05799SMatthew G. Knepley   Not collective
81257cd05799SMatthew G. Knepley 
81267cd05799SMatthew G. Knepley   Input Parameters:
8127a1cb98faSBarry Smith + dm         - The `DM`
8128a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
8129a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
813071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
813171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
813271f0bbf9SMatthew G. Knepley 
813371f0bbf9SMatthew G. Knepley   Output Parameters:
813471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
813571f0bbf9SMatthew G. Knepley . indices    - The dof indices
813620f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
813720f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
813871f0bbf9SMatthew G. Knepley 
8139a1cb98faSBarry Smith   Level: advanced
814071f0bbf9SMatthew G. Knepley 
8141a1cb98faSBarry Smith   Notes:
8142a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
8143a1cb98faSBarry Smith 
8144a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
814571f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
814671f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
814771f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
814871f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
81497cd05799SMatthew G. Knepley 
81501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
81517cd05799SMatthew G. Knepley @*/
8152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8153d71ae5a4SJacob Faibussowitsch {
81547773e69fSMatthew G. Knepley   PetscFunctionBegin;
81557773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81564f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
81579566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
81583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81597773e69fSMatthew G. Knepley }
81607773e69fSMatthew G. Knepley 
8161e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8162d71ae5a4SJacob Faibussowitsch {
8163552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
8164552f7358SJed Brown   PetscInt          *indices;
816571f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
816671f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
8167552f7358SJed Brown   PetscErrorCode     ierr;
8168552f7358SJed Brown 
8169552f7358SJed Brown   PetscFunctionBegin;
8170552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81719566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
81723dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
81739566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
81743dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
8175e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 5);
8176552f7358SJed Brown 
8177e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values));
81780d644c17SKarl Rupp 
81799566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
8180d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
81814a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8182552f7358SJed Brown   if (ierr) {
8183552f7358SJed Brown     PetscMPIInt rank;
8184552f7358SJed Brown 
81859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81869566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81879566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
81889566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81899566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
8190c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
8191552f7358SJed Brown   }
81924a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
81934a1e0b3eSMatthew G. Knepley     PetscInt i;
81949566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
819563a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
81969566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
81974a1e0b3eSMatthew G. Knepley   }
819871f0bbf9SMatthew G. Knepley 
81999566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
82009566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
82013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82024acb8e1eSToby Isaac }
820371f0bbf9SMatthew G. Knepley 
82044a1e0b3eSMatthew G. Knepley /*@C
8205e8e188d2SZach Atkins   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
8206e8e188d2SZach Atkins 
8207e8e188d2SZach Atkins   Not collective
8208e8e188d2SZach Atkins 
8209e8e188d2SZach Atkins   Input Parameters:
8210e8e188d2SZach Atkins + dm            - The `DM`
8211e8e188d2SZach Atkins . section       - The section describing the layout in `v`, or `NULL` to use the default section
8212e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
8213e8e188d2SZach Atkins . A             - The matrix
8214e8e188d2SZach Atkins . point         - The point in the `DM`
8215e8e188d2SZach Atkins . values        - The array of values
8216e8e188d2SZach Atkins - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
8217e8e188d2SZach Atkins 
8218e8e188d2SZach Atkins   Level: intermediate
8219e8e188d2SZach Atkins 
8220e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
8221e8e188d2SZach Atkins @*/
8222e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8223e8e188d2SZach Atkins {
8224e8e188d2SZach Atkins   PetscFunctionBegin;
8225e8e188d2SZach Atkins   PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode));
8226e8e188d2SZach Atkins   PetscFunctionReturn(PETSC_SUCCESS);
8227e8e188d2SZach Atkins }
8228e8e188d2SZach Atkins 
8229e8e188d2SZach Atkins /*@C
823060225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
82314a1e0b3eSMatthew G. Knepley 
82324a1e0b3eSMatthew G. Knepley   Not collective
82334a1e0b3eSMatthew G. Knepley 
82344a1e0b3eSMatthew G. Knepley   Input Parameters:
8235a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
823620f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
8237e8e188d2SZach Atkins . useRowPerm       - The flag to use the closure permutation of the `dmRow` if available
823820f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
8239a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
824020f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
8241e8e188d2SZach Atkins . useColPerm       - The flag to use the closure permutation of the `dmCol` if available
824220f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
82434a1e0b3eSMatthew G. Knepley . A                - The matrix
8244a1cb98faSBarry Smith . point            - The point in the `DM`
82454a1e0b3eSMatthew G. Knepley . values           - The array of values
8246a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
82474a1e0b3eSMatthew G. Knepley 
82484a1e0b3eSMatthew G. Knepley   Level: intermediate
82494a1e0b3eSMatthew G. Knepley 
82501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
82514a1e0b3eSMatthew G. Knepley @*/
8252e8e188d2SZach 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)
8253d71ae5a4SJacob Faibussowitsch {
825471f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
825571f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
825671f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
825771f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
825871f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
825971f0bbf9SMatthew G. Knepley 
826071f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
826171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
82629566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
826371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
82649566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
826571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
8266e8e188d2SZach Atkins   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5);
82679566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
8268e8e188d2SZach Atkins   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6);
82699566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
8270e8e188d2SZach Atkins   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7);
8271e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 9);
827271f0bbf9SMatthew G. Knepley 
8273e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8274e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
827571f0bbf9SMatthew G. Knepley 
82769566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
8277d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
82784a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
827971f0bbf9SMatthew G. Knepley   if (ierr) {
828071f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
828171f0bbf9SMatthew G. Knepley 
82829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
82839566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
82849566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
82859566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
82869566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
82879566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
8288d3d1a6afSToby Isaac   }
828971f0bbf9SMatthew G. Knepley 
8290e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
8291e8e188d2SZach Atkins   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
82929566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
82933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8294552f7358SJed Brown }
8295552f7358SJed Brown 
8296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8297d71ae5a4SJacob Faibussowitsch {
8298de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
8299de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
8300de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
8301de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
830217c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8303de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
8304412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
83054ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
8306de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
8307de41b84cSMatthew G. Knepley 
8308de41b84cSMatthew G. Knepley   PetscFunctionBegin;
8309de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
8310de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
83119566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
8312de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
83139566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
8314de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
83159566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
8316de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
83179566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
8318de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
8319de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
83209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
832163a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
83229566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
83239566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
8324de41b84cSMatthew G. Knepley   /* Column indices */
83259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83264ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8327de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8328de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
83299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8330de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8331de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8332de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8333de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8334de41b84cSMatthew G. Knepley       ++q;
8335de41b84cSMatthew G. Knepley     }
8336de41b84cSMatthew G. Knepley   }
8337de41b84cSMatthew G. Knepley   numCPoints = q;
8338de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8339de41b84cSMatthew G. Knepley     PetscInt fdof;
8340de41b84cSMatthew G. Knepley 
83419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
83424ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8343de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8345de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8346de41b84cSMatthew G. Knepley     }
8347de41b84cSMatthew G. Knepley     numCIndices += dof;
8348de41b84cSMatthew G. Knepley   }
8349de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8350de41b84cSMatthew G. Knepley   /* Row indices */
83519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8352412e9a14SMatthew G. Knepley   {
8353012bc364SMatthew G. Knepley     DMPlexTransform tr;
8354012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8355012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8356012bc364SMatthew G. Knepley 
83579566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
83589566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
83599566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8360012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
83619566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8362412e9a14SMatthew G. Knepley   }
83639566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8364de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8365de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
83669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8367de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
83689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8369de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8370de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
83719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
83724ca5e9f5SMatthew G. Knepley         if (!dof) continue;
83739371c9d4SSatish Balay         for (s = 0; s < q; ++s)
83749371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
83754ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8376de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8377de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8378de41b84cSMatthew G. Knepley         ++q;
8379de41b84cSMatthew G. Knepley       }
8380de41b84cSMatthew G. Knepley     }
83819566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8382de41b84cSMatthew G. Knepley   }
8383de41b84cSMatthew G. Knepley   numFPoints = q;
8384de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8385de41b84cSMatthew G. Knepley     PetscInt fdof;
8386de41b84cSMatthew G. Knepley 
83879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
83884ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8389de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8391de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8392de41b84cSMatthew G. Knepley     }
8393de41b84cSMatthew G. Knepley     numFIndices += dof;
8394de41b84cSMatthew G. Knepley   }
8395de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8396de41b84cSMatthew G. Knepley 
83971dca8a05SBarry 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);
83981dca8a05SBarry 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);
83999566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
84009566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8401de41b84cSMatthew G. Knepley   if (numFields) {
84024acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
84034acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
84044acb8e1eSToby Isaac 
84054acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8408de41b84cSMatthew G. Knepley     }
84094acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
84109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
84124acb8e1eSToby Isaac     }
84134acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
84149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
84164acb8e1eSToby Isaac     }
84174acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84189566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84199566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8420de41b84cSMatthew G. Knepley     }
8421de41b84cSMatthew G. Knepley   } else {
84224acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
84234acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
84244acb8e1eSToby Isaac 
84259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
84274acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
84284acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
84294acb8e1eSToby Isaac 
84309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8432de41b84cSMatthew G. Knepley     }
84334acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
84344acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
84354acb8e1eSToby Isaac 
84369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8438de41b84cSMatthew G. Knepley     }
84399566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
84409566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8441de41b84cSMatthew G. Knepley   }
84429566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
84434acb8e1eSToby Isaac   /* TODO: flips */
8444d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8445de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8446de41b84cSMatthew G. Knepley   if (ierr) {
8447de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8448de41b84cSMatthew G. Knepley 
84499566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
84509566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
84519566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
84529566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
84539566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8454de41b84cSMatthew G. Knepley   }
84559566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
84569566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84579566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
84589566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
84593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8460de41b84cSMatthew G. Knepley }
8461de41b84cSMatthew G. Knepley 
8462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8463d71ae5a4SJacob Faibussowitsch {
84647c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
84657c927364SMatthew G. Knepley   PetscInt       *cpoints      = NULL;
8466230af79eSStefano Zampini   PetscInt        foffsets[32] = {0}, coffsets[32] = {0};
846717c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8468412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
84697c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
84707c927364SMatthew G. Knepley 
84717c927364SMatthew G. Knepley   PetscFunctionBegin;
84727c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
84737c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
84749566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
84757c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
84769566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
84777c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
84789566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
84797c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
84809566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
84817c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
84829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
848363a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
84847c927364SMatthew G. Knepley   /* Column indices */
84859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84867c927364SMatthew G. Knepley   maxFPoints = numCPoints;
84877c927364SMatthew G. Knepley   /* Compress out points not in the section */
84887c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
84899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
84907c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
84917c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
84927c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
84937c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
84947c927364SMatthew G. Knepley       ++q;
84957c927364SMatthew G. Knepley     }
84967c927364SMatthew G. Knepley   }
84977c927364SMatthew G. Knepley   numCPoints = q;
84987c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
84997c927364SMatthew G. Knepley     PetscInt fdof;
85007c927364SMatthew G. Knepley 
85019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
85027c927364SMatthew G. Knepley     if (!dof) continue;
85037c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
85049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
85057c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
85067c927364SMatthew G. Knepley     }
85077c927364SMatthew G. Knepley     numCIndices += dof;
85087c927364SMatthew G. Knepley   }
85097c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
85107c927364SMatthew G. Knepley   /* Row indices */
85119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8512412e9a14SMatthew G. Knepley   {
8513012bc364SMatthew G. Knepley     DMPlexTransform tr;
8514012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8515012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8516012bc364SMatthew G. Knepley 
85179566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
85189566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
85199566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8520012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
85219566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8522412e9a14SMatthew G. Knepley   }
85239566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
85247c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
85257c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
85269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
85277c927364SMatthew G. Knepley     /* Compress out points not in the section */
85289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
85297c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
85307c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
85319566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
85327c927364SMatthew G. Knepley         if (!dof) continue;
85339371c9d4SSatish Balay         for (s = 0; s < q; ++s)
85349371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
85357c927364SMatthew G. Knepley         if (s < q) continue;
85367c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
85377c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
85387c927364SMatthew G. Knepley         ++q;
85397c927364SMatthew G. Knepley       }
85407c927364SMatthew G. Knepley     }
85419566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
85427c927364SMatthew G. Knepley   }
85437c927364SMatthew G. Knepley   numFPoints = q;
85447c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
85457c927364SMatthew G. Knepley     PetscInt fdof;
85467c927364SMatthew G. Knepley 
85479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
85487c927364SMatthew G. Knepley     if (!dof) continue;
85497c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
85509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
85517c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
85527c927364SMatthew G. Knepley     }
85537c927364SMatthew G. Knepley     numFIndices += dof;
85547c927364SMatthew G. Knepley   }
85557c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
85567c927364SMatthew G. Knepley 
85571dca8a05SBarry 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);
85581dca8a05SBarry 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);
85597c927364SMatthew G. Knepley   if (numFields) {
85604acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
85614acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
85624acb8e1eSToby Isaac 
85634acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85667c927364SMatthew G. Knepley     }
85674acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
85689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
85704acb8e1eSToby Isaac     }
85714acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
85729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85739566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
85744acb8e1eSToby Isaac     }
85754acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85769566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85779566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85787c927364SMatthew G. Knepley     }
85797c927364SMatthew G. Knepley   } else {
85804acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
85814acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
85824acb8e1eSToby Isaac 
85839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85854acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
85864acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
85874acb8e1eSToby Isaac 
85889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
85907c927364SMatthew G. Knepley     }
85914acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
85924acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
85934acb8e1eSToby Isaac 
85949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
85967c927364SMatthew G. Knepley     }
85979566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85989566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85997c927364SMatthew G. Knepley   }
86009566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
86019566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
86023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86037c927364SMatthew G. Knepley }
86047c927364SMatthew G. Knepley 
86057cd05799SMatthew G. Knepley /*@C
86067cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
86077cd05799SMatthew G. Knepley 
86087cd05799SMatthew G. Knepley   Input Parameter:
8609a1cb98faSBarry Smith . dm - The `DMPLEX` object
86107cd05799SMatthew G. Knepley 
86117cd05799SMatthew G. Knepley   Output Parameter:
86127cd05799SMatthew G. Knepley . cellHeight - The height of a cell
86137cd05799SMatthew G. Knepley 
86147cd05799SMatthew G. Knepley   Level: developer
86157cd05799SMatthew G. Knepley 
86161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
86177cd05799SMatthew G. Knepley @*/
8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8619d71ae5a4SJacob Faibussowitsch {
8620552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8621552f7358SJed Brown 
8622552f7358SJed Brown   PetscFunctionBegin;
8623552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86244f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8625552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
86263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8627552f7358SJed Brown }
8628552f7358SJed Brown 
86297cd05799SMatthew G. Knepley /*@C
86307cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
86317cd05799SMatthew G. Knepley 
86327cd05799SMatthew G. Knepley   Input Parameters:
8633a1cb98faSBarry Smith + dm         - The `DMPLEX` object
86347cd05799SMatthew G. Knepley - cellHeight - The height of a cell
86357cd05799SMatthew G. Knepley 
86367cd05799SMatthew G. Knepley   Level: developer
86377cd05799SMatthew G. Knepley 
86381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
86397cd05799SMatthew G. Knepley @*/
8640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8641d71ae5a4SJacob Faibussowitsch {
8642552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8643552f7358SJed Brown 
8644552f7358SJed Brown   PetscFunctionBegin;
8645552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8646552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
86473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8648552f7358SJed Brown }
8649552f7358SJed Brown 
8650e6139122SMatthew G. Knepley /*@
86512827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8652e6139122SMatthew G. Knepley 
86532827ebadSStefano Zampini   Input Parameters:
86542827ebadSStefano Zampini + dm - The `DMPLEX` object
86552827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8656e6139122SMatthew G. Knepley 
8657e6139122SMatthew G. Knepley   Output Parameters:
86582827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
86592827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8660e6139122SMatthew G. Knepley 
86612a9f31c0SMatthew G. Knepley   Level: advanced
8662e6139122SMatthew G. Knepley 
86632827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8664e6139122SMatthew G. Knepley @*/
86652827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8666d71ae5a4SJacob Faibussowitsch {
86672827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
86682827ebadSStefano Zampini   DMLabel  label;
86692827ebadSStefano Zampini   PetscInt pStart, pEnd;
8670e6139122SMatthew G. Knepley 
8671e6139122SMatthew G. Knepley   PetscFunctionBegin;
8672e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86732827ebadSStefano Zampini   if (start) {
86744f572ea9SToby Isaac     PetscAssertPointer(start, 3);
86752827ebadSStefano Zampini     *start = 0;
86762827ebadSStefano Zampini   }
86772827ebadSStefano Zampini   if (end) {
86784f572ea9SToby Isaac     PetscAssertPointer(end, 4);
86792827ebadSStefano Zampini     *end = 0;
86802827ebadSStefano Zampini   }
86812827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86822827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
86832827ebadSStefano Zampini   if (mesh->tr) {
86842827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
86852827ebadSStefano Zampini   } else {
86862827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
86872827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
86882827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
86892827ebadSStefano Zampini   }
86903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8691e6139122SMatthew G. Knepley }
8692e6139122SMatthew G. Knepley 
8693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8694d71ae5a4SJacob Faibussowitsch {
8695552f7358SJed Brown   PetscSection section, globalSection;
8696552f7358SJed Brown   PetscInt    *numbers, p;
8697552f7358SJed Brown 
8698552f7358SJed Brown   PetscFunctionBegin;
8699d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
87009566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
87019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
870248a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
87039566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
8704eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection));
87059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8706552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
87079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8708ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8709ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8710552f7358SJed Brown   }
87119566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8712ef48cebcSMatthew G. Knepley   if (globalSize) {
8713ef48cebcSMatthew G. Knepley     PetscLayout layout;
87149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
87159566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
87169566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8717ef48cebcSMatthew G. Knepley   }
87189566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
87199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
87203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8721552f7358SJed Brown }
8722552f7358SJed Brown 
8723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8724d71ae5a4SJacob Faibussowitsch {
8725412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8726552f7358SJed Brown 
8727552f7358SJed Brown   PetscFunctionBegin;
87289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87299566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
87309566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
87319566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
87323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8733552f7358SJed Brown }
873481ed3555SMatthew G. Knepley 
87358dab3259SMatthew G. Knepley /*@
87367cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
87377cd05799SMatthew G. Knepley 
87387cd05799SMatthew G. Knepley   Input Parameter:
8739a1cb98faSBarry Smith . dm - The `DMPLEX` object
87407cd05799SMatthew G. Knepley 
87417cd05799SMatthew G. Knepley   Output Parameter:
87427cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
87437cd05799SMatthew G. Knepley 
87447cd05799SMatthew G. Knepley   Level: developer
87457cd05799SMatthew G. Knepley 
87461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
87477cd05799SMatthew G. Knepley @*/
8748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8749d71ae5a4SJacob Faibussowitsch {
875081ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
875181ed3555SMatthew G. Knepley 
875281ed3555SMatthew G. Knepley   PetscFunctionBegin;
875381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87549566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8755552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
87563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8757552f7358SJed Brown }
8758552f7358SJed Brown 
8759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8760d71ae5a4SJacob Faibussowitsch {
8761412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
876281ed3555SMatthew G. Knepley 
876381ed3555SMatthew G. Knepley   PetscFunctionBegin;
876481ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
87669566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
87673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876881ed3555SMatthew G. Knepley }
876981ed3555SMatthew G. Knepley 
87708dab3259SMatthew G. Knepley /*@
87716aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
87727cd05799SMatthew G. Knepley 
87737cd05799SMatthew G. Knepley   Input Parameter:
8774a1cb98faSBarry Smith . dm - The `DMPLEX` object
87757cd05799SMatthew G. Knepley 
87767cd05799SMatthew G. Knepley   Output Parameter:
87777cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
87787cd05799SMatthew G. Knepley 
87797cd05799SMatthew G. Knepley   Level: developer
87807cd05799SMatthew G. Knepley 
87811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87827cd05799SMatthew G. Knepley @*/
8783d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8784d71ae5a4SJacob Faibussowitsch {
8785552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8786552f7358SJed Brown 
8787552f7358SJed Brown   PetscFunctionBegin;
8788552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87899566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8790552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
87913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8792552f7358SJed Brown }
8793552f7358SJed Brown 
87948dab3259SMatthew G. Knepley /*@
8795966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8796966484cfSJed Brown 
879720f4b53cSBarry Smith   Collective
87987cd05799SMatthew G. Knepley 
87997cd05799SMatthew G. Knepley   Input Parameter:
8800a1cb98faSBarry Smith . dm - The `DMPLEX` object
88017cd05799SMatthew G. Knepley 
88027cd05799SMatthew G. Knepley   Output Parameter:
88037cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
88047cd05799SMatthew G. Knepley 
8805a1cb98faSBarry Smith   Level: developer
8806966484cfSJed Brown 
8807a1cb98faSBarry Smith   Notes:
8808a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8809966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8810966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8811966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8812966484cfSJed Brown 
8813966484cfSJed Brown   The partitioned mesh is
8814966484cfSJed Brown   ```
8815966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8816966484cfSJed Brown   ```
8817966484cfSJed Brown   and its global numbering is
8818966484cfSJed Brown   ```
8819966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8820966484cfSJed Brown   ```
8821966484cfSJed Brown   Then the global numbering is provided as
8822966484cfSJed Brown   ```
8823966484cfSJed Brown   [0] Number of indices in set 5
8824966484cfSJed Brown   [0] 0 0
8825966484cfSJed Brown   [0] 1 1
8826966484cfSJed Brown   [0] 2 3
8827966484cfSJed Brown   [0] 3 4
8828966484cfSJed Brown   [0] 4 -6
8829966484cfSJed Brown   [1] Number of indices in set 3
8830966484cfSJed Brown   [1] 0 2
8831966484cfSJed Brown   [1] 1 5
8832966484cfSJed Brown   [1] 2 6
8833966484cfSJed Brown   ```
8834966484cfSJed Brown 
88351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
88367cd05799SMatthew G. Knepley @*/
8837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8838d71ae5a4SJacob Faibussowitsch {
8839ef48cebcSMatthew G. Knepley   IS        nums[4];
8840862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8841ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
88420c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8843ef48cebcSMatthew G. Knepley 
8844ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8845ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
88470c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
88489566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
88490c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8850862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8851862913ffSStefano Zampini     PetscInt end;
8852862913ffSStefano Zampini 
8853862913ffSStefano Zampini     depths[d] = depth - d;
88549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
88550c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8856862913ffSStefano Zampini   }
88570c15888dSMatthew G. Knepley   if (empty)
88580c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
88590c15888dSMatthew G. Knepley       depths[d] = -1;
88600c15888dSMatthew G. Knepley       starts[d] = -1;
88610c15888dSMatthew G. Knepley     }
88620c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
88631c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8864ad540459SPierre 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]);
88650c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8866ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8867ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8868ef48cebcSMatthew G. Knepley 
88699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
88709566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8871ef48cebcSMatthew G. Knepley     shift += gsize;
8872ef48cebcSMatthew G. Knepley   }
8873d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
88749566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
88753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8876ef48cebcSMatthew G. Knepley }
8877ef48cebcSMatthew G. Knepley 
887808a22f4bSMatthew G. Knepley /*@
887908a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
888008a22f4bSMatthew G. Knepley 
888108a22f4bSMatthew G. Knepley   Input Parameter:
8882a1cb98faSBarry Smith . dm - The `DMPLEX` object
888308a22f4bSMatthew G. Knepley 
888408a22f4bSMatthew G. Knepley   Output Parameter:
888508a22f4bSMatthew G. Knepley . ranks - The rank field
888608a22f4bSMatthew G. Knepley 
8887a1cb98faSBarry Smith   Options Database Key:
888820f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
888908a22f4bSMatthew G. Knepley 
889008a22f4bSMatthew G. Knepley   Level: intermediate
889108a22f4bSMatthew G. Knepley 
88921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
889308a22f4bSMatthew G. Knepley @*/
8894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8895d71ae5a4SJacob Faibussowitsch {
889608a22f4bSMatthew G. Knepley   DM             rdm;
889708a22f4bSMatthew G. Knepley   PetscFE        fe;
889808a22f4bSMatthew G. Knepley   PetscScalar   *r;
889908a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8900a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
890108a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8902a55f9a55SMatthew G. Knepley   PetscBool      simplex;
890308a22f4bSMatthew G. Knepley 
890408a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8905f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89064f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
89079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
89089566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
89099566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
89109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
89119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8912a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
89139566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
89149566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
89159566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89169566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89179566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89189566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
89199566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
89209566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
892108a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
892208a22f4bSMatthew G. Knepley     PetscScalar *lr;
892308a22f4bSMatthew G. Knepley 
89249566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
892571f09efeSPierre Jolivet     if (lr) *lr = rank;
892608a22f4bSMatthew G. Knepley   }
89279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
89289566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
893008a22f4bSMatthew G. Knepley }
893108a22f4bSMatthew G. Knepley 
8932ca8062c8SMatthew G. Knepley /*@
8933acf3173eSStefano Zampini   DMPlexCreateLabelField - Create a field whose value is the label value for that point
893418e14f0cSMatthew G. Knepley 
893518e14f0cSMatthew G. Knepley   Input Parameters:
893620f4b53cSBarry Smith + dm    - The `DMPLEX`
893720f4b53cSBarry Smith - label - The `DMLabel`
893818e14f0cSMatthew G. Knepley 
893918e14f0cSMatthew G. Knepley   Output Parameter:
894018e14f0cSMatthew G. Knepley . val - The label value field
894118e14f0cSMatthew G. Knepley 
894220f4b53cSBarry Smith   Options Database Key:
894320f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
894418e14f0cSMatthew G. Knepley 
894518e14f0cSMatthew G. Knepley   Level: intermediate
894618e14f0cSMatthew G. Knepley 
89471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
894818e14f0cSMatthew G. Knepley @*/
8949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8950d71ae5a4SJacob Faibussowitsch {
89511033741fSStefano Zampini   DM             rdm, plex;
8952acf3173eSStefano Zampini   Vec            lval;
8953acf3173eSStefano Zampini   PetscSection   section;
895418e14f0cSMatthew G. Knepley   PetscFE        fe;
895518e14f0cSMatthew G. Knepley   PetscScalar   *v;
8956acf3173eSStefano Zampini   PetscInt       dim, pStart, pEnd, p, cStart;
8957acf3173eSStefano Zampini   DMPolytopeType ct;
8958acf3173eSStefano Zampini   char           name[PETSC_MAX_PATH_LEN];
8959acf3173eSStefano Zampini   const char    *lname, *prefix;
896018e14f0cSMatthew G. Knepley 
896118e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
896218e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89634f572ea9SToby Isaac   PetscAssertPointer(label, 2);
89644f572ea9SToby Isaac   PetscAssertPointer(val, 3);
89659566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
8966acf3173eSStefano Zampini   PetscCall(DMConvert(rdm, DMPLEX, &plex));
8967acf3173eSStefano Zampini   PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL));
8968acf3173eSStefano Zampini   PetscCall(DMPlexGetCellType(plex, cStart, &ct));
8969acf3173eSStefano Zampini   PetscCall(DMDestroy(&plex));
89709566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
8971acf3173eSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
8972acf3173eSStefano Zampini   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
8973acf3173eSStefano Zampini   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname));
8974acf3173eSStefano Zampini   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe));
8975acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)fe, ""));
89769566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89779566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89789566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89799566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
8980acf3173eSStefano Zampini   PetscCall(DMCreateLocalVector(rdm, &lval));
8981acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)*val, lname));
8982acf3173eSStefano Zampini   PetscCall(DMGetLocalSection(rdm, &section));
8983acf3173eSStefano Zampini   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
8984acf3173eSStefano Zampini   PetscCall(VecGetArray(lval, &v));
8985acf3173eSStefano Zampini   for (p = pStart; p < pEnd; ++p) {
8986acf3173eSStefano Zampini     PetscInt cval, dof, off;
898718e14f0cSMatthew G. Knepley 
8988acf3173eSStefano Zampini     PetscCall(PetscSectionGetDof(section, p, &dof));
8989acf3173eSStefano Zampini     if (!dof) continue;
8990acf3173eSStefano Zampini     PetscCall(DMLabelGetValue(label, p, &cval));
8991acf3173eSStefano Zampini     PetscCall(PetscSectionGetOffset(section, p, &off));
8992acf3173eSStefano Zampini     for (PetscInt d = 0; d < dof; d++) v[off + d] = cval;
899318e14f0cSMatthew G. Knepley   }
8994acf3173eSStefano Zampini   PetscCall(VecRestoreArray(lval, &v));
8995acf3173eSStefano Zampini   PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val));
8996acf3173eSStefano Zampini   PetscCall(VecDestroy(&lval));
89979566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
899918e14f0cSMatthew G. Knepley }
900018e14f0cSMatthew G. Knepley 
900118e14f0cSMatthew G. Knepley /*@
9002ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
9003ca8062c8SMatthew G. Knepley 
900469916449SMatthew G. Knepley   Input Parameter:
9005a1cb98faSBarry Smith . dm - The `DMPLEX` object
9006a1cb98faSBarry Smith 
9007a1cb98faSBarry Smith   Level: developer
9008ca8062c8SMatthew G. Knepley 
900995eb5ee5SVaclav Hapla   Notes:
901095eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
901195eb5ee5SVaclav Hapla 
901220f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9013ca8062c8SMatthew G. Knepley 
90141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9015ca8062c8SMatthew G. Knepley @*/
9016d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
9017d71ae5a4SJacob Faibussowitsch {
9018ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
9019ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
9020ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
902157beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
902257beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
9023ca8062c8SMatthew G. Knepley 
9024ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9025ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90269566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
90279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
90289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
9029ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
90309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9031ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
90329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
90339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
9034ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
903542e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
903642e66dfaSMatthew G. Knepley       PetscInt  d;
903742e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
90389371c9d4SSatish Balay         if (cone[c] == cone[d]) {
90399371c9d4SSatish Balay           dup = PETSC_TRUE;
90409371c9d4SSatish Balay           break;
90419371c9d4SSatish Balay         }
904242e66dfaSMatthew G. Knepley       }
90439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
90449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
9045ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
9046ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
9047ca8062c8SMatthew G. Knepley       }
904842e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
904963a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
905048a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
90519566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
905263a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
905348a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
90549566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
905563a3b9bcSJacob 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]);
9056f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
9057ca8062c8SMatthew G. Knepley       }
905842e66dfaSMatthew G. Knepley     }
90599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
90609371c9d4SSatish Balay     if (p != pp) {
90619371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
90629371c9d4SSatish Balay       continue;
90639371c9d4SSatish Balay     }
90649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
90659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
9066ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
90679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
90689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
9069ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
90709566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
90719371c9d4SSatish Balay         if (cone[c] != pp) {
90729371c9d4SSatish Balay           c = 0;
90739371c9d4SSatish Balay           break;
90749371c9d4SSatish Balay         }
9075ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
9076ca8062c8SMatthew G. Knepley       }
9077ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
907863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
907948a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
90809566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
908163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
908248a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
90839566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
908463a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
9085ca8062c8SMatthew G. Knepley       }
9086ca8062c8SMatthew G. Knepley     }
9087ca8062c8SMatthew G. Knepley   }
908857beb4faSStefano Zampini   if (storagecheck) {
90899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
90909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
909163a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
909257beb4faSStefano Zampini   }
90933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9094ca8062c8SMatthew G. Knepley }
9095ca8062c8SMatthew G. Knepley 
9096412e9a14SMatthew G. Knepley /*
9097412e9a14SMatthew 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.
9098412e9a14SMatthew G. Knepley */
9099d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
9100d71ae5a4SJacob Faibussowitsch {
9101412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
9102412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
9103412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
9104412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
9105412e9a14SMatthew G. Knepley 
9106412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9107412e9a14SMatthew G. Knepley   *unsplit = 0;
9108412e9a14SMatthew G. Knepley   switch (ct) {
9109d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
9110d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
9111d71ae5a4SJacob Faibussowitsch     break;
9112412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
91139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
91149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9115412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
91169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
9117412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
9118412e9a14SMatthew G. Knepley     }
9119412e9a14SMatthew G. Knepley     break;
9120412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
9121412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
91229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
91239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9124412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
91259566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
91269566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
9127412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
91289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
9129412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
9130412e9a14SMatthew G. Knepley           PetscInt p;
91319371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
91329371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
9133412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
9134412e9a14SMatthew G. Knepley         }
9135412e9a14SMatthew G. Knepley       }
9136412e9a14SMatthew G. Knepley     }
9137412e9a14SMatthew G. Knepley     break;
9138d71ae5a4SJacob Faibussowitsch   default:
9139d71ae5a4SJacob Faibussowitsch     break;
9140412e9a14SMatthew G. Knepley   }
9141412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
91429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
9143412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
9144412e9a14SMatthew G. Knepley   }
91453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9146412e9a14SMatthew G. Knepley }
9147412e9a14SMatthew G. Knepley 
9148ca8062c8SMatthew G. Knepley /*@
9149ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
9150ca8062c8SMatthew G. Knepley 
9151ca8062c8SMatthew G. Knepley   Input Parameters:
9152a1cb98faSBarry Smith + dm         - The `DMPLEX` object
915358723a97SMatthew G. Knepley - cellHeight - Normally 0
9154ca8062c8SMatthew G. Knepley 
9155a1cb98faSBarry Smith   Level: developer
9156a1cb98faSBarry Smith 
915795eb5ee5SVaclav Hapla   Notes:
915895eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
915925c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
9160ca8062c8SMatthew G. Knepley 
916120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
916295eb5ee5SVaclav Hapla 
91631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9164ca8062c8SMatthew G. Knepley @*/
9165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
9166d71ae5a4SJacob Faibussowitsch {
9167412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
9168412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
9169412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
9170ca8062c8SMatthew G. Knepley 
9171ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9172ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91739566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
91749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
91759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9176412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9177412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
9178412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
917958723a97SMatthew G. Knepley 
91809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
918163a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
9182412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
9183412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
91849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
918563a3b9bcSJacob 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));
9186412e9a14SMatthew G. Knepley     }
91879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
918858723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
918958723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
9190412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
919158723a97SMatthew G. Knepley     }
91929566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
9193412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
9194412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
9195412e9a14SMatthew G. Knepley       PetscInt unsplit;
919642363296SMatthew G. Knepley 
91979566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9198412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
919942363296SMatthew G. Knepley     }
920063a3b9bcSJacob 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));
920142363296SMatthew G. Knepley   }
92023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9203ca8062c8SMatthew G. Knepley }
92049bf0dad6SMatthew G. Knepley 
92059bf0dad6SMatthew G. Knepley /*@
92069bf0dad6SMatthew 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
92079bf0dad6SMatthew G. Knepley 
920820f4b53cSBarry Smith   Collective
9209899ea2b8SJacob Faibussowitsch 
92109bf0dad6SMatthew G. Knepley   Input Parameters:
9211a1cb98faSBarry Smith + dm         - The `DMPLEX` object
92129bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
92139bf0dad6SMatthew G. Knepley 
9214a1cb98faSBarry Smith   Level: developer
9215a1cb98faSBarry Smith 
921645da879fSVaclav Hapla   Notes:
921745da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
921845da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
921945da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
922045da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
92219bf0dad6SMatthew G. Knepley 
9222a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
922395eb5ee5SVaclav Hapla 
92241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
92259bf0dad6SMatthew G. Knepley @*/
9226d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
9227d71ae5a4SJacob Faibussowitsch {
9228ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
9229899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
92309bf0dad6SMatthew G. Knepley 
92319bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
92329bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92338f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
92343ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
92358f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
92363ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
92373ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9238899ea2b8SJacob Faibussowitsch   }
9239899ea2b8SJacob Faibussowitsch 
92409566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
92419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
92429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9243ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
92449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
92453554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
9246412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
9247412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
9248ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
9249412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
9250412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
92519bf0dad6SMatthew G. Knepley 
92529566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
92539566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9254412e9a14SMatthew G. Knepley       if (unsplit) continue;
92559566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
92569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
92579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
92589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92599bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
92609bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
92619bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
92629bf0dad6SMatthew G. Knepley       }
92639566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
926463a3b9bcSJacob 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);
92659bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
9266d4961f80SStefano Zampini         DMPolytopeType fct;
92679bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
92689bf0dad6SMatthew G. Knepley 
92699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
92709566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
92719bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
92729bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
92739bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
92749bf0dad6SMatthew G. Knepley         }
927563a3b9bcSJacob 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]);
92769bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
9277b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
9278b5a892a1SMatthew G. Knepley             PetscInt v1;
9279b5a892a1SMatthew G. Knepley 
92809566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
928163a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
92829566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
928363a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
92849566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
928563a3b9bcSJacob 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]);
9286b5a892a1SMatthew G. Knepley           }
92879bf0dad6SMatthew G. Knepley         }
92889566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
9289412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
92909bf0dad6SMatthew G. Knepley       }
92919566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
92929566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92939bf0dad6SMatthew G. Knepley     }
92943554e41dSMatthew G. Knepley   }
92953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9296552f7358SJed Brown }
92973913d7c8SMatthew G. Knepley 
9298bb6a34a8SMatthew G. Knepley /*@
9299bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
9300bb6a34a8SMatthew G. Knepley 
9301bb6a34a8SMatthew G. Knepley   Input Parameter:
9302a1cb98faSBarry Smith . dm - The `DMPLEX` object
9303a1cb98faSBarry Smith 
9304a1cb98faSBarry Smith   Level: developer
9305bb6a34a8SMatthew G. Knepley 
930695eb5ee5SVaclav Hapla   Notes:
930795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
930895eb5ee5SVaclav Hapla 
930920f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9310bb6a34a8SMatthew G. Knepley 
93111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9312bb6a34a8SMatthew G. Knepley @*/
9313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
9314d71ae5a4SJacob Faibussowitsch {
9315a2a9e04cSMatthew G. Knepley   Vec       coordinates;
9316bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
9317bb6a34a8SMatthew G. Knepley   PetscReal vol;
931851a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
9319bb6a34a8SMatthew G. Knepley 
9320bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
93219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
93229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
93233ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
93249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
9325bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
93269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9327a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
93289566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
93293ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
9330412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9331412e9a14SMatthew G. Knepley     DMPolytopeType ct;
9332412e9a14SMatthew G. Knepley     PetscInt       unsplit;
9333412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
9334412e9a14SMatthew G. Knepley 
93359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
9336412e9a14SMatthew G. Knepley     switch (ct) {
9337412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
9338412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9339d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9340d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9341d71ae5a4SJacob Faibussowitsch       break;
9342d71ae5a4SJacob Faibussowitsch     default:
9343d71ae5a4SJacob Faibussowitsch       break;
9344412e9a14SMatthew G. Knepley     }
9345412e9a14SMatthew G. Knepley     switch (ct) {
9346412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9347412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9348412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9349d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9350d71ae5a4SJacob Faibussowitsch       continue;
9351d71ae5a4SJacob Faibussowitsch     default:
9352d71ae5a4SJacob Faibussowitsch       break;
9353412e9a14SMatthew G. Knepley     }
93549566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9355412e9a14SMatthew G. Knepley     if (unsplit) continue;
93569566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
93571dca8a05SBarry 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);
935863a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
93596858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
93606858538eSMatthew G. Knepley     if (depth > 1) {
93619566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
93621dca8a05SBarry 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);
936363a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9364bb6a34a8SMatthew G. Knepley     }
9365bb6a34a8SMatthew G. Knepley   }
93663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9367bb6a34a8SMatthew G. Knepley }
9368bb6a34a8SMatthew G. Knepley 
936903da9461SVaclav Hapla /*@
937020f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
93717726db96SVaclav Hapla 
937220f4b53cSBarry Smith   Collective
937303da9461SVaclav Hapla 
937403da9461SVaclav Hapla   Input Parameters:
9375a1cb98faSBarry Smith + dm              - The `DMPLEX` object
937620f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9377a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9378a1cb98faSBarry Smith 
9379a1cb98faSBarry Smith   Level: developer
938003da9461SVaclav Hapla 
9381e83a0d2dSVaclav Hapla   Notes:
9382e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
938303da9461SVaclav Hapla 
9384a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
938595eb5ee5SVaclav Hapla 
9386baca6076SPierre Jolivet   Extra roots can come from periodic cuts, where additional points appear on the boundary
9387d7d32a9aSMatthew G. Knepley 
93881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
938903da9461SVaclav Hapla @*/
9390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9391d71ae5a4SJacob Faibussowitsch {
93927726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
93937726db96SVaclav Hapla   const PetscInt    *locals;
93947726db96SVaclav Hapla   const PetscSFNode *remotes;
9395f0cfc026SVaclav Hapla   PetscBool          distributed;
93967726db96SVaclav Hapla   MPI_Comm           comm;
93977726db96SVaclav Hapla   PetscMPIInt        rank;
939803da9461SVaclav Hapla 
939903da9461SVaclav Hapla   PetscFunctionBegin;
940003da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94017726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
94027726db96SVaclav Hapla   else pointSF = dm->sf;
94037726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
94047726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
94057726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
94067726db96SVaclav Hapla   {
94077726db96SVaclav Hapla     PetscMPIInt mpiFlag;
94087726db96SVaclav Hapla 
94097726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
94107726db96SVaclav 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);
94117726db96SVaclav Hapla   }
94127726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
94139566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
94147726db96SVaclav Hapla   if (!distributed) {
94157726db96SVaclav 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);
94163ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
94178918e3e2SVaclav Hapla   }
94187726db96SVaclav 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);
94197726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
942003da9461SVaclav Hapla 
94217726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
94227726db96SVaclav Hapla   {
94237726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
94247726db96SVaclav Hapla 
94257726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
94267726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9427d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
94287726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
94297726db96SVaclav Hapla   }
94307726db96SVaclav Hapla 
94317726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
94327726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
94337726db96SVaclav 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);
94347726db96SVaclav Hapla   }
94357726db96SVaclav Hapla 
94367726db96SVaclav Hapla   /* Check there are no cells in interface */
94377726db96SVaclav Hapla   if (!overlap) {
94387726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
94397726db96SVaclav Hapla 
94409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9442f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
94437726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9444f5869d18SMatthew G. Knepley 
94457726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
94467726db96SVaclav Hapla     }
944703da9461SVaclav Hapla   }
9448ece87651SVaclav Hapla 
94497726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
94507726db96SVaclav Hapla   {
94517726db96SVaclav Hapla     const PetscInt *rootdegree;
94527726db96SVaclav Hapla 
94537726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
94547726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9455f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
94567726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9457f5869d18SMatthew G. Knepley       const PetscInt *cone;
9458f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9459f5869d18SMatthew G. Knepley 
94609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
94619566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9462f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9463f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
94647726db96SVaclav Hapla           if (locals) {
94659566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
94667726db96SVaclav Hapla           } else {
94677726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
94687726db96SVaclav Hapla           }
946963a3b9bcSJacob 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]);
9470f5869d18SMatthew G. Knepley         }
9471f5869d18SMatthew G. Knepley       }
9472ece87651SVaclav Hapla     }
94737726db96SVaclav Hapla   }
94743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
947503da9461SVaclav Hapla }
947603da9461SVaclav Hapla 
94777f9d8d6cSVaclav Hapla /*@
947820f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
94797f9d8d6cSVaclav Hapla 
94807f9d8d6cSVaclav Hapla   Input Parameter:
9481a1cb98faSBarry Smith . dm - The `DMPLEX` object
9482a1cb98faSBarry Smith 
9483a1cb98faSBarry Smith   Level: developer
94847f9d8d6cSVaclav Hapla 
94857f9d8d6cSVaclav Hapla   Notes:
94867f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
94877f9d8d6cSVaclav Hapla 
948820f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
94897f9d8d6cSVaclav Hapla 
949020f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
94917f9d8d6cSVaclav Hapla 
94921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
94937f9d8d6cSVaclav Hapla @*/
9494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9495d71ae5a4SJacob Faibussowitsch {
94967f9d8d6cSVaclav Hapla   PetscInt cellHeight;
94977f9d8d6cSVaclav Hapla 
9498b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94997f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
95009566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
95019566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
95029566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
95039566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9504d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
95059566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
95063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9507b5a892a1SMatthew G. Knepley }
9508b5a892a1SMatthew G. Knepley 
95099371c9d4SSatish Balay typedef struct cell_stats {
9510068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9511068a5610SStefano Zampini   PetscInt  count;
9512068a5610SStefano Zampini } cell_stats_t;
9513068a5610SStefano Zampini 
9514d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9515d71ae5a4SJacob Faibussowitsch {
9516068a5610SStefano Zampini   PetscInt i, N = *len;
9517068a5610SStefano Zampini 
9518068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9519068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9520068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9521068a5610SStefano Zampini 
9522068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9523068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9524068a5610SStefano Zampini     B->sum += A->sum;
9525068a5610SStefano Zampini     B->squaresum += A->squaresum;
9526068a5610SStefano Zampini     B->count += A->count;
9527068a5610SStefano Zampini   }
9528068a5610SStefano Zampini }
9529068a5610SStefano Zampini 
9530068a5610SStefano Zampini /*@
953143fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9532068a5610SStefano Zampini 
953320f4b53cSBarry Smith   Collective
95348261a58bSMatthew G. Knepley 
9535068a5610SStefano Zampini   Input Parameters:
9536a1cb98faSBarry Smith + dm        - The `DMPLEX` object
953720f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9538a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9539a1cb98faSBarry Smith 
9540a1cb98faSBarry Smith   Level: developer
9541068a5610SStefano Zampini 
954295eb5ee5SVaclav Hapla   Notes:
954395eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
954495eb5ee5SVaclav Hapla 
9545a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9546068a5610SStefano Zampini 
95471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9548068a5610SStefano Zampini @*/
9549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9550d71ae5a4SJacob Faibussowitsch {
9551068a5610SStefano Zampini   DM           dmCoarse;
955243fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
955343fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
955443fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
955543fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9556412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
955743fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9558068a5610SStefano Zampini 
9559068a5610SStefano Zampini   PetscFunctionBegin;
9560068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9561068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9562068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9563068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9564068a5610SStefano Zampini   stats.count                 = 0;
9565068a5610SStefano Zampini 
95669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
95679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
95689566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
95699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
95709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
95719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9572412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9573068a5610SStefano Zampini     PetscInt  i;
9574068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9575068a5610SStefano Zampini 
95769566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
957763a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
957843fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9579068a5610SStefano Zampini       frobJ += J[i] * J[i];
9580068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9581068a5610SStefano Zampini     }
9582068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9583068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9584068a5610SStefano Zampini 
9585068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9586068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9587068a5610SStefano Zampini     stats.sum += cond;
9588068a5610SStefano Zampini     stats.squaresum += cond2;
9589068a5610SStefano Zampini     stats.count++;
95908261a58bSMatthew G. Knepley     if (output && cond > limit) {
959143fa8764SMatthew G. Knepley       PetscSection coordSection;
959243fa8764SMatthew G. Knepley       Vec          coordsLocal;
959343fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
959443fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
959543fa8764SMatthew G. Knepley 
95969566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
95979566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
95989566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
959963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
960043fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
960163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
960243fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
96039566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
96049566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
960543fa8764SMatthew G. Knepley         }
96069566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
960743fa8764SMatthew G. Knepley       }
96089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
960943fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
961043fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
961143fa8764SMatthew G. Knepley 
961243fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
961343fa8764SMatthew G. Knepley           PetscReal len;
961443fa8764SMatthew G. Knepley 
96159566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
961663a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
961743fa8764SMatthew G. Knepley         }
961843fa8764SMatthew G. Knepley       }
96199566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
96209566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
962143fa8764SMatthew G. Knepley     }
9622068a5610SStefano Zampini   }
96239566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9624068a5610SStefano Zampini 
9625068a5610SStefano Zampini   if (size > 1) {
9626068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9627068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9628068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9629068a5610SStefano Zampini     MPI_Op       statReduce;
9630068a5610SStefano Zampini 
96319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
96329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
96339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
96349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
96359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
96369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9637068a5610SStefano Zampini   } else {
96389566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9639068a5610SStefano Zampini   }
9640dd400576SPatrick Sanan   if (rank == 0) {
9641068a5610SStefano Zampini     count = globalStats.count;
9642068a5610SStefano Zampini     min   = globalStats.min;
9643068a5610SStefano Zampini     max   = globalStats.max;
9644068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9645068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9646068a5610SStefano Zampini   }
9647068a5610SStefano Zampini 
964848a46eb9SPierre 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));
96499566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9650068a5610SStefano Zampini 
96519566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9652068a5610SStefano Zampini   if (dmCoarse) {
9653068a5610SStefano Zampini     PetscBool isplex;
9654068a5610SStefano Zampini 
96559566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
96561baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9657068a5610SStefano Zampini   }
96583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9659068a5610SStefano Zampini }
9660068a5610SStefano Zampini 
9661f108dbd7SJacob Faibussowitsch /*@
9662f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9663f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9664f108dbd7SJacob Faibussowitsch 
966520f4b53cSBarry Smith   Collective
9666f108dbd7SJacob Faibussowitsch 
9667f108dbd7SJacob Faibussowitsch   Input Parameters:
9668a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9669a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9670f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9671f108dbd7SJacob Faibussowitsch 
9672f108dbd7SJacob Faibussowitsch   Output Parameters:
967320f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9674a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9675f108dbd7SJacob Faibussowitsch 
9676f108dbd7SJacob Faibussowitsch   Options Database Keys:
9677a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9678f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9679f108dbd7SJacob Faibussowitsch 
9680a1cb98faSBarry Smith   Level: intermediate
9681a1cb98faSBarry Smith 
9682f108dbd7SJacob Faibussowitsch   Notes:
9683a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9684f108dbd7SJacob Faibussowitsch 
9685a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9686f108dbd7SJacob Faibussowitsch 
9687f108dbd7SJacob 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
9688f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9689f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9690f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9691f108dbd7SJacob Faibussowitsch 
9692f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9693f108dbd7SJacob Faibussowitsch 
9694a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9695f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9696f108dbd7SJacob Faibussowitsch 
9697f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9698f108dbd7SJacob Faibussowitsch 
96991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9700f108dbd7SJacob Faibussowitsch @*/
9701d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9702d71ae5a4SJacob Faibussowitsch {
97036ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
97046ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
97056ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9706f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
97076ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9708f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9709f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9710f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9711f108dbd7SJacob Faibussowitsch   IS                     glob;
9712f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9713f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9714f108dbd7SJacob Faibussowitsch 
9715f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9716f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9717ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
97184f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
97196bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
97209566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
97219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
972263a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
97236ed19f2fSJacob Faibussowitsch   {
97246ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
97256ed19f2fSJacob Faibussowitsch 
97269566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9727f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9728f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9729f108dbd7SJacob Faibussowitsch 
97309566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
973198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9732f108dbd7SJacob Faibussowitsch     }
97336ed19f2fSJacob Faibussowitsch   }
9734f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
97354f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
97369566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
97379566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
97389371c9d4SSatish Balay   } else {
97399371c9d4SSatish Balay     *OrthQualLabel = NULL;
97409371c9d4SSatish Balay   }
97419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
97429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
97439566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
97449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
97459566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
97469566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
97479566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
97489566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
97499566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
97509566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
97519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
97529566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
97539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
97549566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
97559566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
97569566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
97579566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
97589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
97596ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
97606ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9761f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9762f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9763898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9764f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9765f108dbd7SJacob Faibussowitsch 
97666ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9767f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9768f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
97699566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
97709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9771f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
97729566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
97736ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
97746ed19f2fSJacob Faibussowitsch       PetscInt         i;
97756ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9776f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9777f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9778f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9779f108dbd7SJacob Faibussowitsch 
9780f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9781f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
97829566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9783f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
97846ed19f2fSJacob Faibussowitsch       {
97856ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
97866ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
97876ed19f2fSJacob Faibussowitsch 
97889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
97899566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
97909566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
97916ed19f2fSJacob Faibussowitsch       }
9792f108dbd7SJacob Faibussowitsch 
9793f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9794f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9795f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9796f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9797f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9798addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9799addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9800addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9801f108dbd7SJacob Faibussowitsch       }
9802addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9803addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9804addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9805f108dbd7SJacob Faibussowitsch 
9806f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9807f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9808f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9809f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9810f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9811f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9812f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9813f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9814f108dbd7SJacob Faibussowitsch       }
9815ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9816ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9817f108dbd7SJacob Faibussowitsch     }
98189566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
98199566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9820f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
98216ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9822f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
98239566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9824f108dbd7SJacob Faibussowitsch     }
9825f108dbd7SJacob Faibussowitsch   }
98269566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
98279566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
98289566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
98299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
98309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
98319566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9832f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
98339566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9834f108dbd7SJacob Faibussowitsch   }
98359566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
9836cd791dc2SBarry Smith   PetscCall(PetscOptionsRestoreViewer(&vwr));
98379566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
98383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9839f108dbd7SJacob Faibussowitsch }
9840f108dbd7SJacob Faibussowitsch 
9841d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
98421eb70e55SToby Isaac  * interpolator construction */
9843d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9844d71ae5a4SJacob Faibussowitsch {
98451eb70e55SToby Isaac   PetscSection section, newSection, gsection;
98461eb70e55SToby Isaac   PetscSF      sf;
98471eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
98481eb70e55SToby Isaac 
98491eb70e55SToby Isaac   PetscFunctionBegin;
98501eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98514f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
98529566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
98539566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9854712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
98551eb70e55SToby Isaac   if (!ghasConstraints) {
98569566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
98571eb70e55SToby Isaac     *odm = dm;
98583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
98591eb70e55SToby Isaac   }
98609566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
98619566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
98629566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
98639566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
9864eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection));
98659566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
98669566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
98673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98681eb70e55SToby Isaac }
98691eb70e55SToby Isaac 
9870d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9871d71ae5a4SJacob Faibussowitsch {
98721eb70e55SToby Isaac   DM        dmco, dmfo;
98731eb70e55SToby Isaac   Mat       interpo;
98741eb70e55SToby Isaac   Vec       rscale;
98751eb70e55SToby Isaac   Vec       cglobalo, clocal;
98761eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
98771eb70e55SToby Isaac   PetscBool regular;
98781eb70e55SToby Isaac 
98791eb70e55SToby Isaac   PetscFunctionBegin;
98809566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
98819566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
98829566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
98839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
98849566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
98859566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
98869566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
98879566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
98889566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
98899566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
98909566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
98919566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
98929566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
98939566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
98949566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
98959566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
98969566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
98979566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
98989566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
98999566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
99009566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
99019566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
99029566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
99039566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
99041eb70e55SToby Isaac   *shift = fglobal;
99059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
99069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
99079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
99089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
99099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
99109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
99119566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
99129566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
99133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99141eb70e55SToby Isaac }
99151eb70e55SToby Isaac 
9916d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9917d71ae5a4SJacob Faibussowitsch {
99181eb70e55SToby Isaac   PetscObject shifto;
99191eb70e55SToby Isaac   Vec         shift;
99201eb70e55SToby Isaac 
99211eb70e55SToby Isaac   PetscFunctionBegin;
99221eb70e55SToby Isaac   if (!interp) {
99231eb70e55SToby Isaac     Vec rscale;
99241eb70e55SToby Isaac 
99259566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
99269566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
99271eb70e55SToby Isaac   } else {
99289566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
99291eb70e55SToby Isaac   }
99309566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
99311eb70e55SToby Isaac   if (!shifto) {
99329566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
99339566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
99341eb70e55SToby Isaac     shifto = (PetscObject)shift;
99359566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
99361eb70e55SToby Isaac   }
99371eb70e55SToby Isaac   shift = (Vec)shifto;
99389566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
99399566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
99409566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
99413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99421eb70e55SToby Isaac }
99431eb70e55SToby Isaac 
9944bceba477SMatthew G. Knepley /* Pointwise interpolation
9945bceba477SMatthew G. Knepley      Just code FEM for now
9946bceba477SMatthew G. Knepley      u^f = I u^c
99474ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
99484ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
99494ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9950bceba477SMatthew G. Knepley */
9951d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9952d71ae5a4SJacob Faibussowitsch {
9953bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9954bceba477SMatthew G. Knepley   PetscInt     m, n;
9955a063dac3SMatthew G. Knepley   void        *ctx;
995668132eb9SMatthew G. Knepley   DM           cdm;
9957cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9958bceba477SMatthew G. Knepley 
9959bceba477SMatthew G. Knepley   PetscFunctionBegin;
99609566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
99619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
99629566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
99639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
996468132eb9SMatthew G. Knepley 
99659566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
99669566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
99679566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
99689566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
99699566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
997068132eb9SMatthew G. Knepley 
99719566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
99729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
99739566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
99749566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
99759566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
99764db47ee9SStefano Zampini   if (scaling) {
99775d1c2e58SMatthew G. Knepley     /* Use naive scaling */
99789566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
99794db47ee9SStefano Zampini   }
99803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9981a063dac3SMatthew G. Knepley }
9982bceba477SMatthew G. Knepley 
9983d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9984d71ae5a4SJacob Faibussowitsch {
99856dbf9973SLawrence Mitchell   VecScatter ctx;
998690748bafSMatthew G. Knepley 
9987a063dac3SMatthew G. Knepley   PetscFunctionBegin;
99889566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
99899566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
99909566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
99913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9992bceba477SMatthew G. Knepley }
9993bceba477SMatthew G. Knepley 
9994d71ae5a4SJacob 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[])
9995d71ae5a4SJacob Faibussowitsch {
999600635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
999700635df3SMatthew G. Knepley   PetscInt       c;
999800635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
99993e9753d6SMatthew G. Knepley }
100003e9753d6SMatthew G. Knepley 
10001d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
10002d71ae5a4SJacob Faibussowitsch {
10003b4937a87SMatthew G. Knepley   DM           dmc;
10004b4937a87SMatthew G. Knepley   PetscDS      ds;
10005b4937a87SMatthew G. Knepley   Vec          ones, locmass;
10006b4937a87SMatthew G. Knepley   IS           cellIS;
10007b4937a87SMatthew G. Knepley   PetscFormKey key;
10008b4937a87SMatthew G. Knepley   PetscInt     depth;
10009b4937a87SMatthew G. Knepley 
10010b4937a87SMatthew G. Knepley   PetscFunctionBegin;
100119566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
100129566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
100139566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
100149566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
100159566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
100169566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
100179566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
100189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
100199566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
100209566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
100219566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
10022b4937a87SMatthew G. Knepley   key.label = NULL;
10023b4937a87SMatthew G. Knepley   key.value = 0;
10024b4937a87SMatthew G. Knepley   key.field = 0;
10025b4937a87SMatthew G. Knepley   key.part  = 0;
100269566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
100279566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
100289566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
100299566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
100309566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
100319566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
100329566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
100339566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
100343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10035b4937a87SMatthew G. Knepley }
10036b4937a87SMatthew G. Knepley 
10037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
10038d71ae5a4SJacob Faibussowitsch {
10039bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
10040bd041c0cSMatthew G. Knepley   PetscInt     m, n;
10041bd041c0cSMatthew G. Knepley   void        *ctx;
10042bd041c0cSMatthew G. Knepley   DM           cdm;
10043bd041c0cSMatthew G. Knepley   PetscBool    regular;
10044bd041c0cSMatthew G. Knepley 
10045bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
100463e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
100473e9753d6SMatthew G. Knepley     DM            dmc;
100483e9753d6SMatthew G. Knepley     PetscDS       ds;
10049b4937a87SMatthew G. Knepley     PetscWeakForm wf;
100503e9753d6SMatthew G. Knepley     Vec           u;
100513e9753d6SMatthew G. Knepley     IS            cellIS;
1005206ad1575SMatthew G. Knepley     PetscFormKey  key;
100533e9753d6SMatthew G. Knepley     PetscInt      depth;
100543e9753d6SMatthew G. Knepley 
100559566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
100569566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
100579566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
100589566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
100599566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
100609566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
100619566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
100628d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
100639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
100649566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
100659566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
100666528b96dSMatthew G. Knepley     key.label = NULL;
100676528b96dSMatthew G. Knepley     key.value = 0;
100686528b96dSMatthew G. Knepley     key.field = 0;
1006906ad1575SMatthew G. Knepley     key.part  = 0;
100709566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
100719566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
100728d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
100739566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
100743e9753d6SMatthew G. Knepley   } else {
100759566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
100769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
100779566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
100789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
10079bd041c0cSMatthew G. Knepley 
100809566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
100819566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
100829566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
100839566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
10084bd041c0cSMatthew G. Knepley 
100859566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
100869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
100879566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
100889566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
100893e9753d6SMatthew G. Knepley   }
100909566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
100913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10092bd041c0cSMatthew G. Knepley }
10093bd041c0cSMatthew G. Knepley 
100940aef6b92SMatthew G. Knepley /*@
100950aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100960aef6b92SMatthew G. Knepley 
100970aef6b92SMatthew G. Knepley   Input Parameter:
10098a1cb98faSBarry Smith . dm - The `DMPLEX` object
100990aef6b92SMatthew G. Knepley 
101000aef6b92SMatthew G. Knepley   Output Parameter:
101010aef6b92SMatthew G. Knepley . regular - The flag
101020aef6b92SMatthew G. Knepley 
101030aef6b92SMatthew G. Knepley   Level: intermediate
101040aef6b92SMatthew G. Knepley 
101051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
101060aef6b92SMatthew G. Knepley @*/
10107d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
10108d71ae5a4SJacob Faibussowitsch {
101090aef6b92SMatthew G. Knepley   PetscFunctionBegin;
101100aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101114f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
101120aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
101133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101140aef6b92SMatthew G. Knepley }
101150aef6b92SMatthew G. Knepley 
101160aef6b92SMatthew G. Knepley /*@
101170aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
101180aef6b92SMatthew G. Knepley 
101190aef6b92SMatthew G. Knepley   Input Parameters:
10120a1cb98faSBarry Smith + dm      - The `DMPLEX` object
101210aef6b92SMatthew G. Knepley - regular - The flag
101220aef6b92SMatthew G. Knepley 
101230aef6b92SMatthew G. Knepley   Level: intermediate
101240aef6b92SMatthew G. Knepley 
101251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
101260aef6b92SMatthew G. Knepley @*/
10127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
10128d71ae5a4SJacob Faibussowitsch {
101290aef6b92SMatthew G. Knepley   PetscFunctionBegin;
101300aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101310aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
101323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
101330aef6b92SMatthew G. Knepley }
101340aef6b92SMatthew G. Knepley 
10135a68b90caSToby Isaac /*@
10136f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
10137a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
10138a68b90caSToby Isaac 
10139a1cb98faSBarry Smith   Not Collective
10140a68b90caSToby Isaac 
10141f899ff85SJose E. Roman   Input Parameter:
10142a1cb98faSBarry Smith . dm - The `DMPLEX` object
10143a68b90caSToby Isaac 
10144a68b90caSToby Isaac   Output Parameters:
1014520f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
1014620f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
10147a68b90caSToby Isaac 
10148a68b90caSToby Isaac   Level: intermediate
10149a68b90caSToby Isaac 
101501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
10151a68b90caSToby Isaac @*/
10152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
10153d71ae5a4SJacob Faibussowitsch {
10154a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
10155a68b90caSToby Isaac 
10156a68b90caSToby Isaac   PetscFunctionBegin;
10157a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101589566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
10159a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
10160a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
101613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10162a68b90caSToby Isaac }
10163a68b90caSToby Isaac 
10164a68b90caSToby Isaac /*@
10165a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
10166a68b90caSToby Isaac 
1016720f4b53cSBarry Smith   Collective
10168a68b90caSToby Isaac 
10169a68b90caSToby Isaac   Input Parameters:
10170a1cb98faSBarry Smith + dm            - The `DMPLEX` object
10171a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
10172a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10173a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10174a68b90caSToby Isaac 
10175a68b90caSToby Isaac   Level: intermediate
10176a68b90caSToby Isaac 
10177a1cb98faSBarry Smith   Notes:
10178a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
10179a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
10180a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
10181a4e35b19SJacob Faibussowitsch 
10182a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
10183a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
10184a1cb98faSBarry Smith 
1018520f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
10186a1cb98faSBarry Smith 
101871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
10188a68b90caSToby Isaac @*/
10189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
10190d71ae5a4SJacob Faibussowitsch {
10191a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
10192e228b242SToby Isaac   PetscMPIInt result;
10193a68b90caSToby Isaac 
10194a68b90caSToby Isaac   PetscFunctionBegin;
10195a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10196e228b242SToby Isaac   if (anchorSection) {
10197e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
101989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
101991dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
10200e228b242SToby Isaac   }
10201e228b242SToby Isaac   if (anchorIS) {
10202e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
102039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
102041dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
10205e228b242SToby Isaac   }
10206a68b90caSToby Isaac 
102079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
102089566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
10209a68b90caSToby Isaac   plex->anchorSection = anchorSection;
10210a68b90caSToby Isaac 
102119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
102129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
10213a68b90caSToby Isaac   plex->anchorIS = anchorIS;
10214a68b90caSToby Isaac 
10215cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
10216a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
10217a68b90caSToby Isaac     const PetscInt *anchors;
10218a68b90caSToby Isaac 
102199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
102209566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
102219566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
10222a68b90caSToby Isaac     for (a = 0; a < size; a++) {
10223a68b90caSToby Isaac       PetscInt p;
10224a68b90caSToby Isaac 
10225a68b90caSToby Isaac       p = anchors[a];
10226a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
10227a68b90caSToby Isaac         PetscInt dof;
10228a68b90caSToby Isaac 
102299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10230a68b90caSToby Isaac         if (dof) {
102319566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
1023263a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
10233a68b90caSToby Isaac         }
10234a68b90caSToby Isaac       }
10235a68b90caSToby Isaac     }
102369566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
10237a68b90caSToby Isaac   }
10238f7c74593SToby Isaac   /* reset the generic constraints */
102399566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
102403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10241a68b90caSToby Isaac }
10242a68b90caSToby Isaac 
10243d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
10244d71ae5a4SJacob Faibussowitsch {
10245f7c74593SToby Isaac   PetscSection anchorSection;
102466995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
10247a68b90caSToby Isaac 
10248a68b90caSToby Isaac   PetscFunctionBegin;
10249a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
102519566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
102529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
102536995de1eSToby Isaac   if (numFields) {
10254719ab38cSToby Isaac     PetscInt f;
102559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
10256719ab38cSToby Isaac 
10257719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
10258719ab38cSToby Isaac       PetscInt numComp;
10259719ab38cSToby Isaac 
102609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
102619566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
10262719ab38cSToby Isaac     }
102636995de1eSToby Isaac   }
102649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
102659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
102666995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
102676995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
102686995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
102699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
10270a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
102719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10272a68b90caSToby Isaac     if (dof) {
102739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
102749566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
10275a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
102769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
102779566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
10278a68b90caSToby Isaac       }
10279a68b90caSToby Isaac     }
10280a68b90caSToby Isaac   }
102819566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
102829566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
102833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10284a68b90caSToby Isaac }
10285a68b90caSToby Isaac 
10286d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
10287d71ae5a4SJacob Faibussowitsch {
10288f7c74593SToby Isaac   PetscSection    aSec;
10289ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
102900ac89760SToby Isaac   const PetscInt *anchors;
102910ac89760SToby Isaac   PetscInt        numFields, f;
1029266ad2231SToby Isaac   IS              aIS;
10293e19f7ee6SMark Adams   MatType         mtype;
10294e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
102950ac89760SToby Isaac 
102960ac89760SToby Isaac   PetscFunctionBegin;
102970ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
102999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
103009566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
103019566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
103029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
103039566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
103049566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
103059566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
10306e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
10307e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
10308e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
103099566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
103109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
103119566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
103126995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
103139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
103149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
103159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
103160ac89760SToby Isaac   i[0] = 0;
103179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
103180ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
10319f19733c5SToby Isaac     PetscInt rDof, rOff, r;
10320f19733c5SToby Isaac 
103219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
10322f19733c5SToby Isaac     if (!rDof) continue;
103239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103240ac89760SToby Isaac     if (numFields) {
103250ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
103260ac89760SToby Isaac         annz = 0;
10327f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
10328f19733c5SToby Isaac           a = anchors[rOff + r];
10329ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103309566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
103310ac89760SToby Isaac           annz += aDof;
103320ac89760SToby Isaac         }
103339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
103349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
10335ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
103360ac89760SToby Isaac       }
103372f7452b8SBarry Smith     } else {
103380ac89760SToby Isaac       annz = 0;
103399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103400ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10341ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10342ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
103439566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
103440ac89760SToby Isaac         annz += aDof;
103450ac89760SToby Isaac       }
103469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10348ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
103490ac89760SToby Isaac     }
103500ac89760SToby Isaac   }
103510ac89760SToby Isaac   nnz = i[m];
103529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
103530ac89760SToby Isaac   offset = 0;
103540ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
103550ac89760SToby Isaac     if (numFields) {
103560ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
103579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
103580ac89760SToby Isaac         for (q = 0; q < dof; q++) {
103590ac89760SToby Isaac           PetscInt rDof, rOff, r;
103609566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103620ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
103630ac89760SToby Isaac             PetscInt s;
103640ac89760SToby Isaac 
103650ac89760SToby Isaac             a = anchors[rOff + r];
10366ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
103679566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
103689566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10369ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103700ac89760SToby Isaac           }
103710ac89760SToby Isaac         }
103720ac89760SToby Isaac       }
103732f7452b8SBarry Smith     } else {
103749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103750ac89760SToby Isaac       for (q = 0; q < dof; q++) {
103760ac89760SToby Isaac         PetscInt rDof, rOff, r;
103779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103789566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103790ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
103800ac89760SToby Isaac           PetscInt s;
103810ac89760SToby Isaac 
103820ac89760SToby Isaac           a = anchors[rOff + r];
10383ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
103859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10386ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103870ac89760SToby Isaac         }
103880ac89760SToby Isaac       }
103890ac89760SToby Isaac     }
103900ac89760SToby Isaac   }
103919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
103929566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
103939566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
103949566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
103953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103960ac89760SToby Isaac }
103970ac89760SToby Isaac 
10398d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10399d71ae5a4SJacob Faibussowitsch {
10400f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10401f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1040266ad2231SToby Isaac   Mat          cMat;
1040366ad2231SToby Isaac 
1040466ad2231SToby Isaac   PetscFunctionBegin;
1040566ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
104069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1040766ad2231SToby Isaac   if (anchorSection) {
1040844a7f3ddSMatthew G. Knepley     PetscInt Nf;
10409e228b242SToby Isaac 
104109566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
104119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
104129566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
104139566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
104149566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
104159566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
104169566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
104179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1041866ad2231SToby Isaac   }
104193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1042066ad2231SToby Isaac }
10421a93c429eSMatthew G. Knepley 
10422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10423d71ae5a4SJacob Faibussowitsch {
10424a93c429eSMatthew G. Knepley   IS           subis;
10425a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10426a93c429eSMatthew G. Knepley 
10427a93c429eSMatthew G. Knepley   PetscFunctionBegin;
104289566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1042928b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1043028b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10431a93c429eSMatthew G. Knepley   /* Create subdomain */
104329566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10433a93c429eSMatthew G. Knepley   /* Create submodel */
104349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
104359566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
104369566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
104379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
104389566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10439a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10440a93c429eSMatthew G. Knepley   if (is) {
10441a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10442a93c429eSMatthew G. Knepley     IS              spIS;
10443a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10444a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10445a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10446a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10447a93c429eSMatthew G. Knepley 
104489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
104499566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
104509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
104519566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
104529566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
104539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10454a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10455a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10456a93c429eSMatthew G. Knepley 
104579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10458a93c429eSMatthew G. Knepley       if (gdof > 0) {
10459a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10460a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10461a93c429eSMatthew G. Knepley 
104629566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
104639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10464a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10465a93c429eSMatthew G. Knepley         }
10466a93c429eSMatthew G. Knepley         subSize += pSubSize;
10467a93c429eSMatthew G. Knepley         if (pSubSize) {
10468a93c429eSMatthew G. Knepley           if (bs < 0) {
10469a93c429eSMatthew G. Knepley             bs = pSubSize;
10470a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10471a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10472a93c429eSMatthew G. Knepley             bs = 1;
10473a93c429eSMatthew G. Knepley           }
10474a93c429eSMatthew G. Knepley         }
10475a93c429eSMatthew G. Knepley       }
10476a93c429eSMatthew G. Knepley     }
10477a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
104789371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
104799371c9d4SSatish Balay     bsLocal[1] = bs;
104809566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
104819371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
104829371c9d4SSatish Balay       bs = 1;
104839371c9d4SSatish Balay     } else {
104849371c9d4SSatish Balay       bs = bsMinMax[0];
104859371c9d4SSatish Balay     }
104869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10487a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10488a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10489a93c429eSMatthew G. Knepley 
104909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10491a93c429eSMatthew G. Knepley       if (gdof > 0) {
10492a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10493a93c429eSMatthew G. Knepley 
104949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10495a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10496a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10497a93c429eSMatthew G. Knepley 
10498a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10499a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
105009566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
105019566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10502a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10503a93c429eSMatthew G. Knepley           }
105049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
105059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10506ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10507a93c429eSMatthew G. Knepley         }
10508a93c429eSMatthew G. Knepley       }
10509a93c429eSMatthew G. Knepley     }
105109566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
105119566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10512a93c429eSMatthew G. Knepley     if (bs > 1) {
10513a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10514a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10515a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10516a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
105179371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
105189371c9d4SSatish Balay             set = 0;
105199371c9d4SSatish Balay             break;
105209371c9d4SSatish Balay           }
10521a93c429eSMatthew G. Knepley         }
10522a93c429eSMatthew G. Knepley       }
105239566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10524a93c429eSMatthew G. Knepley     }
10525a93c429eSMatthew G. Knepley     /* Attach nullspace */
10526a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10527a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10528a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10529a93c429eSMatthew G. Knepley     }
10530a93c429eSMatthew G. Knepley     if (f < Nf) {
10531a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
105329566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
105336823f3c5SBlaise Bourdin 
105349566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
105359566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10536a93c429eSMatthew G. Knepley     }
10537a93c429eSMatthew G. Knepley   }
105383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10539a93c429eSMatthew G. Knepley }
10540c0f0dcc3SMatthew G. Knepley 
10541c0f0dcc3SMatthew G. Knepley /*@
10542c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10543c0f0dcc3SMatthew G. Knepley 
10544a1cb98faSBarry Smith   Input Parameters:
10545a1cb98faSBarry Smith + dm    - The `DM`
10546a1cb98faSBarry Smith - dummy - unused argument
10547a1cb98faSBarry Smith 
10548a1cb98faSBarry Smith   Options Database Key:
10549a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10550c0f0dcc3SMatthew G. Knepley 
10551c0f0dcc3SMatthew G. Knepley   Level: developer
10552c0f0dcc3SMatthew G. Knepley 
105531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10554c0f0dcc3SMatthew G. Knepley @*/
10555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10556d71ae5a4SJacob Faibussowitsch {
10557b665b14eSToby Isaac   PetscLogHandler default_handler;
10558b665b14eSToby Isaac 
105592611ad71SToby Isaac   PetscFunctionBegin;
105602611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10561b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10562b665b14eSToby Isaac   if (default_handler) {
10563c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10564c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10565c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10566c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10567c0f0dcc3SMatthew G. Knepley     const char        *name;
10568c0f0dcc3SMatthew G. Knepley 
105699566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
105709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
105719566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
105729566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10573b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10574c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10575c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10576c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1057763a3b9bcSJacob 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)));
105782611ad71SToby Isaac   } else {
10579b665b14eSToby 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.");
105802611ad71SToby Isaac   }
105813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10582c0f0dcc3SMatthew G. Knepley }
10583