xref: /petsc/src/dm/impls/plex/plex.c (revision c789d87f46ca5c660d7c474d70d10563d3b4ba98)
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>
11*c789d87fSToby Isaac #include <petscblaslapack.h>
12552f7358SJed Brown 
13552f7358SJed Brown /* Logging support */
1402f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad;
15172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate;
16552f7358SJed Brown 
17f39ec787SMatthew G. Knepley PetscBool  Plexcite       = PETSC_FALSE;
18f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n"
19f39ec787SMatthew G. Knepley                             "title     = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n"
20f39ec787SMatthew G. Knepley                             "author    = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n"
21f39ec787SMatthew G. Knepley                             "journal   = {SIAM Journal on Scientific Computing},\n"
22f39ec787SMatthew G. Knepley                             "volume    = {38},\n"
23f39ec787SMatthew G. Knepley                             "number    = {5},\n"
24f39ec787SMatthew G. Knepley                             "pages     = {S143--S155},\n"
25f39ec787SMatthew G. Knepley                             "eprint    = {http://arxiv.org/abs/1506.07749},\n"
26f39ec787SMatthew G. Knepley                             "doi       = {10.1137/15M1026092},\n"
27f39ec787SMatthew G. Knepley                             "year      = {2016},\n"
28f39ec787SMatthew G. Knepley                             "petsc_uses={DMPlex},\n}\n";
29f39ec787SMatthew G. Knepley 
305a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
31552f7358SJed Brown 
32e5337592SStefano Zampini /*@
339318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
349318fe57SMatthew G. Knepley 
359318fe57SMatthew G. Knepley   Input Parameter:
36a1cb98faSBarry Smith . dm - The `DMPLEX` object
379318fe57SMatthew G. Knepley 
389318fe57SMatthew G. Knepley   Output Parameter:
399318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
409318fe57SMatthew G. Knepley 
419318fe57SMatthew G. Knepley   Level: intermediate
429318fe57SMatthew G. Knepley 
43a1cb98faSBarry Smith   Note:
44a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
45a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
46a1cb98faSBarry Smith 
471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
489318fe57SMatthew G. Knepley @*/
49d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
50d71ae5a4SJacob Faibussowitsch {
519318fe57SMatthew G. Knepley   DMPolytopeType ct;
529318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
539318fe57SMatthew G. Knepley 
549318fe57SMatthew G. Knepley   PetscFunctionBegin;
559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
569371c9d4SSatish Balay   if (cEnd <= cStart) {
579371c9d4SSatish Balay     *simplex = PETSC_FALSE;
583ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
599371c9d4SSatish Balay   }
609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
619318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639318fe57SMatthew G. Knepley }
649318fe57SMatthew G. Knepley 
659318fe57SMatthew G. Knepley /*@
66412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
67e5337592SStefano Zampini 
68d8d19677SJose E. Roman   Input Parameters:
69a1cb98faSBarry Smith + dm     - The `DMPLEX` object
70412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
71e5337592SStefano Zampini 
72e5337592SStefano Zampini   Output Parameters:
73412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
7440196513SBarry Smith - cEnd   - The upper bound on "normal" cells
75e5337592SStefano Zampini 
76412e9a14SMatthew G. Knepley   Level: developer
77e5337592SStefano Zampini 
78a1cb98faSBarry Smith   Note:
795ae96e2bSMatthew G. Knepley   This function requires that tensor cells are ordered last.
80a1cb98faSBarry Smith 
812827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()`
82e5337592SStefano Zampini @*/
83d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
84d71ae5a4SJacob Faibussowitsch {
855ae96e2bSMatthew G. Knepley   DMLabel         ctLabel;
865ae96e2bSMatthew G. Knepley   IS              valueIS;
875ae96e2bSMatthew G. Knepley   const PetscInt *ctypes;
885ae96e2bSMatthew G. Knepley   PetscInt        Nct, cS = PETSC_MAX_INT, cE = 0;
89e5337592SStefano Zampini 
90e5337592SStefano Zampini   PetscFunctionBegin;
919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
925ae96e2bSMatthew G. Knepley   PetscCall(DMLabelGetValueIS(ctLabel, &valueIS));
935ae96e2bSMatthew G. Knepley   PetscCall(ISGetLocalSize(valueIS, &Nct));
945ae96e2bSMatthew G. Knepley   PetscCall(ISGetIndices(valueIS, &ctypes));
955ae96e2bSMatthew G. Knepley   if (!Nct) cS = cE = 0;
965ae96e2bSMatthew G. Knepley   for (PetscInt t = 0; t < Nct; ++t) {
97c306944fSJed Brown     const DMPolytopeType ct = (DMPolytopeType)ctypes[t];
985ae96e2bSMatthew G. Knepley     PetscInt             ctS, ctE, ht;
995ae96e2bSMatthew G. Knepley 
1005ae96e2bSMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) {
1015ae96e2bSMatthew G. Knepley       // If any cells are not typed, just use all cells
1025ae96e2bSMatthew G. Knepley       PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd));
1035ae96e2bSMatthew G. Knepley       break;
1045ae96e2bSMatthew G. Knepley     }
105c306944fSJed Brown     if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue;
1065ae96e2bSMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE));
1075ae96e2bSMatthew G. Knepley     if (ctS >= ctE) continue;
1085ae96e2bSMatthew G. Knepley     // Check that a point has the right height
1095ae96e2bSMatthew G. Knepley     PetscCall(DMPlexGetPointHeight(dm, ctS, &ht));
1105ae96e2bSMatthew G. Knepley     if (ht != height) continue;
1115ae96e2bSMatthew G. Knepley     cS = PetscMin(cS, ctS);
1125ae96e2bSMatthew G. Knepley     cE = PetscMax(cE, ctE);
1135ae96e2bSMatthew G. Knepley   }
1145ae96e2bSMatthew G. Knepley   PetscCall(ISDestroy(&valueIS));
115695799ffSMatthew G. Knepley   // Reset label for fast lookup
116695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
117412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
118412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120e5337592SStefano Zampini }
121e5337592SStefano Zampini 
1229c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft)
1239c600e38SMatt McGurn {
1249c600e38SMatt McGurn   PetscInt                 cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t;
1259c600e38SMatt McGurn   PetscInt                *sStart, *sEnd;
1269c600e38SMatt McGurn   PetscViewerVTKFieldType *ft;
1279c600e38SMatt McGurn   PetscInt                 vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1];
1289c600e38SMatt McGurn   DMLabel                  depthLabel, ctLabel;
1299c600e38SMatt McGurn 
1309c600e38SMatt McGurn   PetscFunctionBegin;
1319c600e38SMatt McGurn   /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */
1329c600e38SMatt McGurn   PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1));
1339c600e38SMatt McGurn   PetscCall(DMGetCoordinateDim(dm, &cdim));
1349c600e38SMatt McGurn   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1359c600e38SMatt McGurn   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1369c600e38SMatt McGurn   if (field >= 0) {
1379c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES]));
1389c600e38SMatt McGurn   } else {
1399c600e38SMatt McGurn     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES]));
1409c600e38SMatt McGurn   }
1419c600e38SMatt McGurn 
1429c600e38SMatt McGurn   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
1439c600e38SMatt McGurn   PetscCall(DMPlexGetDepth(dm, &depth));
1449c600e38SMatt McGurn   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
1459c600e38SMatt McGurn   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1469c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1479c600e38SMatt McGurn     const DMPolytopeType ict = (DMPolytopeType)c;
1489c600e38SMatt McGurn     PetscInt             dep;
1499c600e38SMatt McGurn 
1509c600e38SMatt McGurn     if (ict == DM_POLYTOPE_FV_GHOST) continue;
1519c600e38SMatt McGurn     PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1529c600e38SMatt McGurn     if (pStart >= 0) {
1539c600e38SMatt McGurn       PetscCall(DMLabelGetValue(depthLabel, cStart, &dep));
1549c600e38SMatt McGurn       if (dep != depth - cellHeight) continue;
1559c600e38SMatt McGurn     }
1569c600e38SMatt McGurn     if (field >= 0) {
1579c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c]));
1589c600e38SMatt McGurn     } else {
1599c600e38SMatt McGurn       if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c]));
1609c600e38SMatt McGurn     }
1619c600e38SMatt McGurn   }
1629c600e38SMatt McGurn 
1639c600e38SMatt McGurn   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
1649c600e38SMatt McGurn   *types = 0;
1659c600e38SMatt McGurn 
1669c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) {
1679c600e38SMatt McGurn     if (globalvcdof[c]) ++(*types);
1689c600e38SMatt McGurn   }
1699c600e38SMatt McGurn 
1709c600e38SMatt McGurn   PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft));
1719c600e38SMatt McGurn   t = 0;
1729c600e38SMatt McGurn   if (globalvcdof[DM_NUM_POLYTOPES]) {
1739c600e38SMatt McGurn     sStart[t] = vStart;
1749c600e38SMatt McGurn     sEnd[t]   = vEnd;
1759c600e38SMatt McGurn     ft[t]     = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
1769c600e38SMatt McGurn     ++t;
1779c600e38SMatt McGurn   }
1789c600e38SMatt McGurn 
1799c600e38SMatt McGurn   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1809c600e38SMatt McGurn     if (globalvcdof[c]) {
1819c600e38SMatt McGurn       const DMPolytopeType ict = (DMPolytopeType)c;
1829c600e38SMatt McGurn 
1839c600e38SMatt McGurn       PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd));
1849c600e38SMatt McGurn       sStart[t] = cStart;
1859c600e38SMatt McGurn       sEnd[t]   = cEnd;
1869c600e38SMatt McGurn       ft[t]     = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD;
1879c600e38SMatt McGurn       ++t;
1889c600e38SMatt McGurn     }
1899c600e38SMatt McGurn   }
1909c600e38SMatt McGurn 
1914ad8454bSPierre Jolivet   if (!*types) {
1929c600e38SMatt McGurn     if (field >= 0) {
1939c600e38SMatt McGurn       const char *fieldname;
1949c600e38SMatt McGurn 
1959c600e38SMatt McGurn       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
1969c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
1979c600e38SMatt McGurn     } else {
1989c600e38SMatt McGurn       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
1999c600e38SMatt McGurn     }
2009c600e38SMatt McGurn   }
2019c600e38SMatt McGurn 
2029c600e38SMatt McGurn   *ssStart = sStart;
2039c600e38SMatt McGurn   *ssEnd   = sEnd;
2049c600e38SMatt McGurn   *sft     = ft;
2059c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2069c600e38SMatt McGurn }
2079c600e38SMatt McGurn 
2089c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft)
2099c600e38SMatt McGurn {
2109c600e38SMatt McGurn   PetscFunctionBegin;
2119c600e38SMatt McGurn   PetscCall(PetscFree3(*sStart, *sEnd, *ft));
2129c600e38SMatt McGurn   PetscFunctionReturn(PETSC_SUCCESS);
2139c600e38SMatt McGurn }
2149c600e38SMatt McGurn 
215d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
216d71ae5a4SJacob Faibussowitsch {
217412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
218a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
2197e42fee7SMatthew G. Knepley 
2207e42fee7SMatthew G. Knepley   PetscFunctionBegin;
221e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
2229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
2239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
2259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
2267e42fee7SMatthew G. Knepley   if (field >= 0) {
2279566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
2289566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
2297e42fee7SMatthew G. Knepley   } else {
2309566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
2319566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
2327e42fee7SMatthew G. Knepley   }
233712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
234a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
2357e42fee7SMatthew G. Knepley     *sStart = vStart;
2367e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
237f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
2387e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
239a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
2407e42fee7SMatthew G. Knepley     *sStart = cStart;
2417e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
242f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
2437e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
244e630c359SToby Isaac   } else {
245e630c359SToby Isaac     if (field >= 0) {
246e630c359SToby Isaac       const char *fieldname;
247e630c359SToby Isaac 
2489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
24963a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
250e630c359SToby Isaac     } else {
25163a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
252e630c359SToby Isaac     }
253e630c359SToby Isaac   }
2543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2557e42fee7SMatthew G. Knepley }
2567e42fee7SMatthew G. Knepley 
2576913077dSMatthew G. Knepley /*@
2586913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
2596913077dSMatthew G. Knepley 
26020f4b53cSBarry Smith   Collective
2616913077dSMatthew G. Knepley 
2626913077dSMatthew G. Knepley   Input Parameters:
263a1cb98faSBarry Smith + dm     - The `DMPLEX` object
2646913077dSMatthew G. Knepley . n      - The number of vectors
2656913077dSMatthew G. Knepley . u      - The array of local vectors
266a1cb98faSBarry Smith - viewer - The `PetscViewer`
2676913077dSMatthew G. Knepley 
2686913077dSMatthew G. Knepley   Level: advanced
2696913077dSMatthew G. Knepley 
2701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
2716913077dSMatthew G. Knepley @*/
272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
273d71ae5a4SJacob Faibussowitsch {
2746913077dSMatthew G. Knepley   PetscDS            ds;
2756913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
2766913077dSMatthew G. Knepley   PetscDrawLG        lg;
2776913077dSMatthew G. Knepley   Vec                coordinates;
2786913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
2796913077dSMatthew G. Knepley   PetscReal         *vals;
2806913077dSMatthew G. Knepley   PetscInt          *Nc;
2816913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
2826913077dSMatthew G. Knepley   char             **names;
2836913077dSMatthew G. Knepley 
2846913077dSMatthew G. Knepley   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
2869566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
2879566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
2889566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
2896913077dSMatthew G. Knepley 
2909566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2913ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
2929566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
2936913077dSMatthew G. Knepley 
2949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2956913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2966913077dSMatthew G. Knepley     const char *vname;
2976913077dSMatthew G. Knepley 
2989566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
2996913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
3006913077dSMatthew G. Knepley       PetscObject disc;
3016913077dSMatthew G. Knepley       const char *fname;
3026913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
3036913077dSMatthew G. Knepley 
3049566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
3056913077dSMatthew G. Knepley       /* TODO Create names for components */
3066913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
3079566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
308c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
309c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
310c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
3119566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
3126913077dSMatthew G. Knepley       }
3136913077dSMatthew G. Knepley     }
3146913077dSMatthew G. Knepley   }
3159566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
3166913077dSMatthew G. Knepley   /* Just add P_1 support for now */
3179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3199566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
3209566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
3216913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
3226913077dSMatthew G. Knepley     PetscScalar *x, *svals;
3236913077dSMatthew G. Knepley 
3249566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
3256913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
3269566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
3276913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
3286913077dSMatthew G. Knepley     }
3299566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
3306913077dSMatthew G. Knepley   }
3319566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
3329566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
3339566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
3349566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
3356913077dSMatthew G. Knepley 
3369566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
3379566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
3383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3396913077dSMatthew G. Knepley }
3406913077dSMatthew G. Knepley 
341d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
342d71ae5a4SJacob Faibussowitsch {
3436913077dSMatthew G. Knepley   DM dm;
3446913077dSMatthew G. Knepley 
3456913077dSMatthew G. Knepley   PetscFunctionBegin;
3469566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
3479566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
3483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3496913077dSMatthew G. Knepley }
3506913077dSMatthew G. Knepley 
351d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
352d71ae5a4SJacob Faibussowitsch {
353e412dcbdSMatthew G. Knepley   DM                 dm;
354d1df6f1dSMatthew G. Knepley   PetscSection       s;
355e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
356e412dcbdSMatthew G. Knepley   DM                 cdm;
357e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
358e412dcbdSMatthew G. Knepley   Vec                coordinates;
359c9c77995SMatthew G. Knepley   const PetscScalar *array;
360c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
361339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
3626913077dSMatthew G. Knepley   PetscBool          flg;
363d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
364e412dcbdSMatthew G. Knepley   const char        *name;
365339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
366e412dcbdSMatthew G. Knepley 
367e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
3689566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3699566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3719566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
3729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
3739566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
3749566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
3759566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
3769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
3779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
3789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
379e412dcbdSMatthew G. Knepley 
3809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
3819566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
382e412dcbdSMatthew G. Knepley 
3839566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
384c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
3859566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
386e412dcbdSMatthew G. Knepley 
387d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
388d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
389d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
390d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
391d1df6f1dSMatthew G. Knepley     IS          fis;
392d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
393d1df6f1dSMatthew G. Knepley     const char *fname;
394d1df6f1dSMatthew G. Knepley 
3959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
397d1df6f1dSMatthew G. Knepley 
3989566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
399ad540459SPierre Jolivet     else prefix[0] = '\0';
400d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4019566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
4029566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
4039566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
4049566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
405d1df6f1dSMatthew G. Knepley     }
406d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
407d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
408d1df6f1dSMatthew G. Knepley 
4099566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
41063a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
41163a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
4129566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
413d1df6f1dSMatthew G. Knepley 
414d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
4159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
416339e3443SMatthew G. Knepley       if (!flg) {
4179566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
4189566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
419d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
420339e3443SMatthew G. Knepley       }
421c9c77995SMatthew G. Knepley 
4229566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
4239566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
424c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
4259566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
426e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
42799a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
428c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
429c9c77995SMatthew G. Knepley         PetscBool          isDG;
430e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
431e412dcbdSMatthew G. Knepley 
4329566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
433339e3443SMatthew G. Knepley         if (a) {
434d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
435339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
436339e3443SMatthew G. Knepley         } else {
437339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
438339e3443SMatthew G. Knepley           PetscInt     numVals, va;
439339e3443SMatthew G. Knepley 
4409566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
44163a3b9bcSJacob Faibussowitsch           PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals);
442d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
443d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
444d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
445d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
446339e3443SMatthew G. Knepley             break;
447d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
448d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
449d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / (Nc * 2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp + numVals / (Nc * 2)]), vbound[0], vbound[1]);
450d1df6f1dSMatthew G. Knepley             break;
451d71ae5a4SJacob Faibussowitsch           default:
452d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
453339e3443SMatthew G. Knepley           }
4549566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
455339e3443SMatthew G. Knepley         }
456c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
457e412dcbdSMatthew G. Knepley         switch (numCoords) {
458e412dcbdSMatthew G. Knepley         case 6:
4599edc3542SMatthew Knepley         case 12: /* Localized triangle */
4609566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
461e412dcbdSMatthew G. Knepley           break;
462e412dcbdSMatthew G. Knepley         case 8:
4639edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
4649566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]));
4659566063dSJacob Faibussowitsch           PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]));
466e412dcbdSMatthew G. Knepley           break;
467d71ae5a4SJacob Faibussowitsch         default:
468d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
469e412dcbdSMatthew G. Knepley         }
470c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
471e412dcbdSMatthew G. Knepley       }
4729566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
4739566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
4749566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
4759566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
476d1df6f1dSMatthew G. Knepley     }
477d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
4789566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
4799566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
4809566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
481d1df6f1dSMatthew G. Knepley     }
482d1df6f1dSMatthew G. Knepley   }
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
484e412dcbdSMatthew G. Knepley }
485e412dcbdSMatthew G. Knepley 
486d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
487d71ae5a4SJacob Faibussowitsch {
4886913077dSMatthew G. Knepley   DM        dm;
4896913077dSMatthew G. Knepley   PetscDraw draw;
4906913077dSMatthew G. Knepley   PetscInt  dim;
4916913077dSMatthew G. Knepley   PetscBool isnull;
4926913077dSMatthew G. Knepley 
4936913077dSMatthew G. Knepley   PetscFunctionBegin;
4949566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4959566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4963ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4976913077dSMatthew G. Knepley 
4989566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
5006913077dSMatthew G. Knepley   switch (dim) {
501d71ae5a4SJacob Faibussowitsch   case 1:
502d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
503d71ae5a4SJacob Faibussowitsch     break;
504d71ae5a4SJacob Faibussowitsch   case 2:
505d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
506d71ae5a4SJacob Faibussowitsch     break;
507d71ae5a4SJacob Faibussowitsch   default:
508d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
5096913077dSMatthew G. Knepley   }
5103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5116913077dSMatthew G. Knepley }
5126913077dSMatthew G. Knepley 
513d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
514d71ae5a4SJacob Faibussowitsch {
515684b87d9SLisandro Dalcin   DM                      dm;
516684b87d9SLisandro Dalcin   Vec                     locv;
517684b87d9SLisandro Dalcin   const char             *name;
518684b87d9SLisandro Dalcin   PetscSection            section;
519684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
520e630c359SToby Isaac   PetscInt                numFields;
521684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
522684b87d9SLisandro Dalcin 
523684b87d9SLisandro Dalcin   PetscFunctionBegin;
5249566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
5259566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
5289566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
5299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
5309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
531e630c359SToby Isaac   if (!numFields) {
5329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
5339566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
534e630c359SToby Isaac   } else {
535e630c359SToby Isaac     PetscInt f;
536e630c359SToby Isaac 
537e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
5389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
539e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
5409566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
5419566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
542e630c359SToby Isaac     }
5439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
544e630c359SToby Isaac   }
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546684b87d9SLisandro Dalcin }
547684b87d9SLisandro Dalcin 
548d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
549d71ae5a4SJacob Faibussowitsch {
550552f7358SJed Brown   DM        dm;
5515f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
552552f7358SJed Brown 
553552f7358SJed Brown   PetscFunctionBegin;
5549566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
55528b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5605f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5615f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
562684b87d9SLisandro Dalcin     PetscInt    i, numFields;
563684b87d9SLisandro Dalcin     PetscObject fe;
564ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
565684b87d9SLisandro Dalcin     Vec         locv = v;
566684b87d9SLisandro Dalcin     const char *name;
567684b87d9SLisandro Dalcin     PetscInt    step;
568684b87d9SLisandro Dalcin     PetscReal   time;
569ef31f671SMatthew G. Knepley 
5709566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
571684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
5729566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
5739371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
5749371c9d4SSatish Balay         fem = PETSC_TRUE;
5759371c9d4SSatish Balay         break;
5769371c9d4SSatish Balay       }
577ef31f671SMatthew G. Knepley     }
578684b87d9SLisandro Dalcin     if (fem) {
579798534f6SMatthew G. Knepley       PetscObject isZero;
580798534f6SMatthew G. Knepley 
5819566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
5829566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
5839566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
5849566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5859566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5869566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
5879566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
5889566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
589ef31f671SMatthew G. Knepley     }
590552f7358SJed Brown     if (isvtk) {
5919566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
592b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
593b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5949566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
595b136c2c9SMatthew G. Knepley #else
596b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
597b136c2c9SMatthew G. Knepley #endif
598f13a32a3SMatthew G. Knepley     } else if (isdraw) {
5999566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
600684b87d9SLisandro Dalcin     } else if (isglvis) {
6019566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
6029566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
6039566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
6045f34f2dcSJed Brown     } else if (iscgns) {
6055f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
6065f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
6075f34f2dcSJed Brown #else
6085f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
6095f34f2dcSJed Brown #endif
610684b87d9SLisandro Dalcin     }
611798534f6SMatthew G. Knepley     if (fem) {
6129566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6139566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
614798534f6SMatthew G. Knepley     }
615552f7358SJed Brown   } else {
616684b87d9SLisandro Dalcin     PetscBool isseq;
617684b87d9SLisandro Dalcin 
6189566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6199566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6209566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
621552f7358SJed Brown   }
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
623552f7358SJed Brown }
624552f7358SJed Brown 
625d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
626d71ae5a4SJacob Faibussowitsch {
627552f7358SJed Brown   DM        dm;
6285f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
629552f7358SJed Brown 
630552f7358SJed Brown   PetscFunctionBegin;
6319566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
6369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
6375f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
6389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6395f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
640552f7358SJed Brown     Vec         locv;
641798534f6SMatthew G. Knepley     PetscObject isZero;
642552f7358SJed Brown     const char *name;
643552f7358SJed Brown 
6449566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
6459566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
6479566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
6489566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
6499566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
6509566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
6519566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
6529566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
6539566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
654b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
655b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6569566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
657b136c2c9SMatthew G. Knepley #else
658b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
659b136c2c9SMatthew G. Knepley #endif
6606823f3c5SBlaise Bourdin   } else if (isexodusii) {
6616823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6629566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
6636823f3c5SBlaise Bourdin #else
6646823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6656823f3c5SBlaise Bourdin #endif
666552f7358SJed Brown   } else {
667684b87d9SLisandro Dalcin     PetscBool isseq;
668684b87d9SLisandro Dalcin 
6699566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6709566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6719566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
672552f7358SJed Brown   }
6733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
674552f7358SJed Brown }
675552f7358SJed Brown 
676d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
677d71ae5a4SJacob Faibussowitsch {
678d930f514SMatthew G. Knepley   DM                dm;
679d930f514SMatthew G. Knepley   MPI_Comm          comm;
680d930f514SMatthew G. Knepley   PetscViewerFormat format;
681d930f514SMatthew G. Knepley   Vec               v;
682d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
683d930f514SMatthew G. Knepley 
684d930f514SMatthew G. Knepley   PetscFunctionBegin;
6859566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
68728b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6889566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
691d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
692a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
693a8ad634aSStefano Zampini     /* this need a better fix */
694a8ad634aSStefano Zampini     if (dm->useNatural) {
695a8ad634aSStefano Zampini       if (dm->sfNatural) {
696d930f514SMatthew G. Knepley         const char *vecname;
697d930f514SMatthew G. Knepley         PetscInt    n, nroots;
698d930f514SMatthew G. Knepley 
6999566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
7009566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
701d930f514SMatthew G. Knepley         if (n == nroots) {
702f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7039566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
7049566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
7059566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7069566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
707d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
708d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
709a8ad634aSStefano Zampini     } else v = originalv;
710a8ad634aSStefano Zampini   } else v = originalv;
711a8ad634aSStefano Zampini 
712d930f514SMatthew G. Knepley   if (ishdf5) {
713d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7149566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
715d930f514SMatthew G. Knepley #else
716d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
717d930f514SMatthew G. Knepley #endif
718d930f514SMatthew G. Knepley   } else if (isvtk) {
719d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
720d930f514SMatthew G. Knepley   } else {
721d930f514SMatthew G. Knepley     PetscBool isseq;
722d930f514SMatthew G. Knepley 
7239566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
7249566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
7259566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
726d930f514SMatthew G. Knepley   }
727f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
729d930f514SMatthew G. Knepley }
730d930f514SMatthew G. Knepley 
731d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
732d71ae5a4SJacob Faibussowitsch {
7332c40f234SMatthew G. Knepley   DM        dm;
7342c40f234SMatthew G. Knepley   PetscBool ishdf5;
7352c40f234SMatthew G. Knepley 
7362c40f234SMatthew G. Knepley   PetscFunctionBegin;
7379566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
73828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7402c40f234SMatthew G. Knepley   if (ishdf5) {
7412c40f234SMatthew G. Knepley     DM          dmBC;
7422c40f234SMatthew G. Knepley     Vec         gv;
7432c40f234SMatthew G. Knepley     const char *name;
7442c40f234SMatthew G. Knepley 
7459566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
7469566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
7479566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
7489566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
7499566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
7509566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
7519566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
7529566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
7531baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7552c40f234SMatthew G. Knepley }
7562c40f234SMatthew G. Knepley 
757d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
758d71ae5a4SJacob Faibussowitsch {
7592c40f234SMatthew G. Knepley   DM        dm;
7606823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
7612c40f234SMatthew G. Knepley 
7622c40f234SMatthew G. Knepley   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
76428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
7669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
7672c40f234SMatthew G. Knepley   if (ishdf5) {
768878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
7699566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
770b136c2c9SMatthew G. Knepley #else
771b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
772878b459fSMatthew G. Knepley #endif
7736823f3c5SBlaise Bourdin   } else if (isexodusii) {
7746823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
7759566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
7766823f3c5SBlaise Bourdin #else
7776823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
7786823f3c5SBlaise Bourdin #endif
7791baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
781552f7358SJed Brown }
782552f7358SJed Brown 
783d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
784d71ae5a4SJacob Faibussowitsch {
785d930f514SMatthew G. Knepley   DM                dm;
786d930f514SMatthew G. Knepley   PetscViewerFormat format;
787d930f514SMatthew G. Knepley   PetscBool         ishdf5;
788d930f514SMatthew G. Knepley 
789d930f514SMatthew G. Knepley   PetscFunctionBegin;
7909566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
79128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
7929566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
794d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
795a8ad634aSStefano Zampini     if (dm->useNatural) {
796d930f514SMatthew G. Knepley       if (dm->sfNatural) {
797d930f514SMatthew G. Knepley         if (ishdf5) {
798d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
799d930f514SMatthew G. Knepley           Vec         v;
800d930f514SMatthew G. Knepley           const char *vecname;
801d930f514SMatthew G. Knepley 
802f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
8039566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
8049566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
8059566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
8069566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
8079566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
808f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
809d930f514SMatthew G. Knepley #else
810d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
811d930f514SMatthew G. Knepley #endif
812d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
813d930f514SMatthew G. Knepley       }
8141baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
815d930f514SMatthew G. Knepley   }
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817d930f514SMatthew G. Knepley }
818d930f514SMatthew G. Knepley 
819d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
820d71ae5a4SJacob Faibussowitsch {
821731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
822731e8ddeSMatthew G. Knepley   Vec                coordinates;
823ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
824731e8ddeSMatthew G. Knepley   const char        *name[4];
825731e8ddeSMatthew G. Knepley   const PetscScalar *a;
826731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
827731e8ddeSMatthew G. Knepley 
828731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
8299566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
8339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
8349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
8369566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
837731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
838731e8ddeSMatthew G. Knepley   name[1]       = "edge";
839731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
840731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
841731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
842731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
843ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
844731e8ddeSMatthew G. Knepley 
8459566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
84663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
8479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
849731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
850731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
851731e8ddeSMatthew G. Knepley 
852731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
8539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
854731e8ddeSMatthew G. Knepley       if (!dof) continue;
8559566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
8569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
85763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
858731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
8599566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
860731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
8619566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
8629566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
863731e8ddeSMatthew G. Knepley         }
8649566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
865731e8ddeSMatthew G. Knepley       }
8669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
867731e8ddeSMatthew G. Knepley     }
8689566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
870731e8ddeSMatthew G. Knepley   }
8719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
8723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
873731e8ddeSMatthew G. Knepley }
874731e8ddeSMatthew G. Knepley 
8759371c9d4SSatish Balay typedef enum {
8769371c9d4SSatish Balay   CS_CARTESIAN,
8779371c9d4SSatish Balay   CS_POLAR,
8789371c9d4SSatish Balay   CS_CYLINDRICAL,
8799371c9d4SSatish Balay   CS_SPHERICAL
8809371c9d4SSatish Balay } CoordSystem;
88119ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
88219ad8254SMatthew G. Knepley 
883d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
884d71ae5a4SJacob Faibussowitsch {
88519ad8254SMatthew G. Knepley   PetscInt i;
88619ad8254SMatthew G. Knepley 
88719ad8254SMatthew G. Knepley   PetscFunctionBegin;
88819ad8254SMatthew G. Knepley   if (dim > 3) {
8899566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
89019ad8254SMatthew G. Knepley   } else {
891bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
89219ad8254SMatthew G. Knepley 
89319ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
89419ad8254SMatthew G. Knepley     switch (cs) {
8959371c9d4SSatish Balay     case CS_CARTESIAN:
8969371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8979371c9d4SSatish Balay       break;
89819ad8254SMatthew G. Knepley     case CS_POLAR:
89963a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
90019ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90119ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90219ad8254SMatthew G. Knepley       break;
90319ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
90463a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
90519ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
90619ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
90719ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
90819ad8254SMatthew G. Knepley       break;
90919ad8254SMatthew G. Knepley     case CS_SPHERICAL:
91063a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
91119ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
91219ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
91319ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
91419ad8254SMatthew G. Knepley       break;
91519ad8254SMatthew G. Knepley     }
9169566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
91719ad8254SMatthew G. Knepley   }
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91919ad8254SMatthew G. Knepley }
92019ad8254SMatthew G. Knepley 
921d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
922d71ae5a4SJacob Faibussowitsch {
923552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
9246858538eSMatthew G. Knepley   DM                cdm, cdmCell;
9256858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
9266858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
927552f7358SJed Brown   PetscViewerFormat format;
928552f7358SJed Brown 
929552f7358SJed Brown   PetscFunctionBegin;
9309566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
931552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
932552f7358SJed Brown     const char *name;
933f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
9349318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
935552f7358SJed Brown     PetscMPIInt rank, size;
936552f7358SJed Brown 
9379f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9389f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9399f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9409f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9419f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9429f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9459566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
9469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
9489566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
95063a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
95163a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
95263a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
95363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
9549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
95563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
956552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
957552f7358SJed Brown       PetscInt dof, off, s;
958552f7358SJed Brown 
9599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
9609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
96148a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
962552f7358SJed Brown     }
9639566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
96463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
96563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
966552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
967552f7358SJed Brown       PetscInt dof, off, c;
968552f7358SJed Brown 
9699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
9709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
97148a46eb9SPierre Jolivet       for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
972552f7358SJed Brown     }
9739566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
9749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9753d2e540fSStefano Zampini     if (coordSection && coordinates) {
97619ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
9776858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
9786858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
97919ad8254SMatthew G. Knepley       PetscMPIInt        rank;
98019ad8254SMatthew G. Knepley       const char        *name;
98119ad8254SMatthew G. Knepley 
9829566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
9839566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
9849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
98563a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
9869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
9876858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
9886858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
9896858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
9906858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
9919566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
99263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
99363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9949566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
99519ad8254SMatthew G. Knepley 
9969566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9976858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
9999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
100019ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
100119ad8254SMatthew G. Knepley         PetscInt dof, off;
100219ad8254SMatthew G. Knepley 
10036858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
10049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
10059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
10066858538eSMatthew G. Knepley           if (dof) {
100763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10089566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
10099566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
101019ad8254SMatthew G. Knepley           }
10116858538eSMatthew G. Knepley         }
10126858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
10136858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
10146858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
10156858538eSMatthew G. Knepley           if (dof) {
10166858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
10176858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
10186858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
10196858538eSMatthew G. Knepley           }
10206858538eSMatthew G. Knepley         }
10216858538eSMatthew G. Knepley       }
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
10239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
10249566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
10256858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
10263d2e540fSStefano Zampini     }
10279566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10289566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
10299318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
10309318fe57SMatthew G. Knepley       DMLabel     label;
10319318fe57SMatthew G. Knepley       PetscBool   isdepth;
10329318fe57SMatthew G. Knepley       const char *name;
10339318fe57SMatthew G. Knepley 
10349566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
10359566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
10369318fe57SMatthew G. Knepley       if (isdepth) continue;
10379566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
10389566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
10399318fe57SMatthew G. Knepley     }
1040552f7358SJed Brown     if (size > 1) {
1041552f7358SJed Brown       PetscSF sf;
1042552f7358SJed Brown 
10439566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
10449566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
1045552f7358SJed Brown     }
10464e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
10479566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1048552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
10490588280cSMatthew G. Knepley     const char  *name, *color;
10500588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
10510588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
1052fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
1053552f7358SJed Brown     PetscReal    scale      = 2.0;
105478081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
1055b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
10560588280cSMatthew G. Knepley     double       tcoords[3];
1057552f7358SJed Brown     PetscScalar *coords;
1058b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
1059552f7358SJed Brown     PetscMPIInt  rank, size;
10600588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
1061b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
1062fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
1063fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
1064552f7358SJed Brown 
10659f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
10669f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
10679f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10689f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
10699f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
10709f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
10719566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
10729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
10739566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
10740588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
10750588280cSMatthew G. Knepley     numColors  = 10;
10760588280cSMatthew G. Knepley     numLColors = 10;
10779566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
10789566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
10799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
10809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
1081b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
1082b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
1083b7f6ffafSMatthew G. Knepley     n = 4;
10849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
10851dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
1086bd3611e6SMatthew G. Knepley     n = 4;
10879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
10881dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
10899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
10900588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
10919566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
10920588280cSMatthew G. Knepley     if (!useColors) {
10930588280cSMatthew G. Knepley       numColors = 3;
10949566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10950588280cSMatthew G. Knepley     }
10969566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10970588280cSMatthew G. Knepley     if (!useColors) {
10980588280cSMatthew G. Knepley       numLColors = 4;
10999566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
11000588280cSMatthew G. Knepley     }
11019566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1102b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
11039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
11041dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1105202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
11069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1107fe1cc32dSStefano Zampini 
1108fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
11099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
11109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
11119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
11129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1113fe1cc32dSStefano Zampini     if (lflg) {
1114fe1cc32dSStefano Zampini       DMLabel lbl;
1115fe1cc32dSStefano Zampini 
11169566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1117fe1cc32dSStefano Zampini       if (lbl) {
1118fe1cc32dSStefano Zampini         PetscInt val, defval;
1119fe1cc32dSStefano Zampini 
11209566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
11219566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1122fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1123fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1124fe1cc32dSStefano Zampini           PetscInt  closureSize;
1125fe1cc32dSStefano Zampini 
11269566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1127fe1cc32dSStefano Zampini           if (val == defval) continue;
1128fe1cc32dSStefano Zampini 
11299566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
113048a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
11319566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1132fe1cc32dSStefano Zampini         }
1133fe1cc32dSStefano Zampini       }
1134fe1cc32dSStefano Zampini     }
1135fe1cc32dSStefano Zampini 
11369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
11379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
11389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
11399566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
11400588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1141552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1142552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1143552f7358SJed Brown \\usetikzlibrary{arrows}\n\
11445f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
11450588280cSMatthew G. Knepley     if (size > 1) {
11469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1147770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
114863a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
114963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1150770b213bSMatthew G Knepley       }
11519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
11520588280cSMatthew G. Knepley     }
1153b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1154b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1155b7f6ffafSMatthew G. Knepley 
115663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
115763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
115863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
11599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
116063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
116163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
11629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
116363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
116463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
116563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
116663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
11679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1168b7f6ffafSMatthew G. Knepley     }
11699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1170fe1cc32dSStefano Zampini 
1171552f7358SJed Brown     /* Plot vertices */
11729566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
11739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1174552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1175552f7358SJed Brown       PetscInt  off, dof, d;
11760588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1177552f7358SJed Brown 
1178fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
11799566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
11809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
11819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
118263a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
11830588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
11840588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1185c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
11860588280cSMatthew G. Knepley       }
11870588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
11889371c9d4SSatish Balay       if (dim == 3) {
11899371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
11909371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
11919371c9d4SSatish Balay         tcoords[2]    = -tmp;
11929371c9d4SSatish Balay       }
1193552f7358SJed Brown       for (d = 0; d < dof; ++d) {
11949566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11959566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1196552f7358SJed Brown       }
1197b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1198b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11990588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
12000588280cSMatthew G. Knepley         PetscInt val;
12019566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
12029371c9d4SSatish Balay         if (val >= 0) {
12039371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12049371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12059371c9d4SSatish Balay           break;
12069371c9d4SSatish Balay         }
12070588280cSMatthew G. Knepley       }
1208b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
120963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1210b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
121163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
12121baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1213552f7358SJed Brown     }
12149566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1216b7f6ffafSMatthew G. Knepley     /* Plot edges */
1217b7f6ffafSMatthew G. Knepley     if (plotEdges) {
12189566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
12199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1220b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1221b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1222b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1223b7f6ffafSMatthew G. Knepley 
1224b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
12259566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
122663a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
12279566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
12289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
12299566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
12309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
12319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1232b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1233b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1234b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1235b7f6ffafSMatthew G. Knepley         }
1236b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12379371c9d4SSatish Balay         if (dim == 3) {
12389371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12399371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12409371c9d4SSatish Balay           tcoords[2]    = -tmp;
12419371c9d4SSatish Balay         }
1242b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
12439566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12449566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1245b7f6ffafSMatthew G. Knepley         }
1246b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1247b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1248b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1249b7f6ffafSMatthew G. Knepley           PetscInt val;
1250bd3611e6SMatthew G. Knepley           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12519371c9d4SSatish Balay           if (val >= 0) {
12529371c9d4SSatish Balay             color = lcolors[l % numLColors];
12539371c9d4SSatish Balay             break;
12549371c9d4SSatish Balay           }
1255b7f6ffafSMatthew G. Knepley         }
125663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1257b7f6ffafSMatthew G. Knepley       }
12589566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
12609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1261b7f6ffafSMatthew G. Knepley     }
1262846a3e8bSMatthew G. Knepley     /* Plot cells */
1263b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1264846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1265846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1266846a3e8bSMatthew G. Knepley 
1267fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1268846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1269846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1270846a3e8bSMatthew G. Knepley           PetscInt val;
12719566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
12729371c9d4SSatish Balay           if (val >= 0) {
12739371c9d4SSatish Balay             color = lcolors[l % numLColors];
12749371c9d4SSatish Balay             break;
12759371c9d4SSatish Balay           }
1276846a3e8bSMatthew G. Knepley         }
12779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
127863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1279846a3e8bSMatthew G. Knepley       }
1280846a3e8bSMatthew G. Knepley     } else {
1281b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1282846a3e8bSMatthew G. Knepley 
1283b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1284b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1285fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
12869566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1287c306944fSJed Brown         if (DMPolytopeTypeIsHybrid(ct)) {
1288b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1289b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1290b7f6ffafSMatthew G. Knepley 
12919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
12929566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1293b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1294b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1295b7f6ffafSMatthew G. Knepley 
12969566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
129763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1298b7f6ffafSMatthew G. Knepley           }
1299b7f6ffafSMatthew G. Knepley         } else {
1300b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1301b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1302b7f6ffafSMatthew G. Knepley 
13039566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1304846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1305846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1306846a3e8bSMatthew G. Knepley 
1307b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1308846a3e8bSMatthew G. Knepley           }
13099566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1310b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1311b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1312b7f6ffafSMatthew G. Knepley 
1313b7f6ffafSMatthew G. Knepley             if (v > 0) {
1314b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1315b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1316b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1317b7f6ffafSMatthew G. Knepley 
13189371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
13199371c9d4SSatish Balay                 endpoints[1] = vertex;
13209566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
132163a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
132263a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
13239566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
13241baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1325b7f6ffafSMatthew G. Knepley             }
132663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1327b7f6ffafSMatthew G. Knepley           }
13289566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
13299566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1330846a3e8bSMatthew G. Knepley         }
1331846a3e8bSMatthew G. Knepley       }
1332b7f6ffafSMatthew G. Knepley     }
1333846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1334846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1335846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1336c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1337c713ec31SMatthew G. Knepley       const PetscScalar *array;
1338c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1339c713ec31SMatthew G. Knepley       PetscBool          isDG;
1340846a3e8bSMatthew G. Knepley 
1341fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1342c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1343c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1344c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
13459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1346c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1347c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1348c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1349846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1350846a3e8bSMatthew G. Knepley         }
1351846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
13529371c9d4SSatish Balay         if (cdim == 3) {
13539371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
13549371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
13559371c9d4SSatish Balay           tcoords[2]    = -tmp;
13569371c9d4SSatish Balay         }
1357ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1358846a3e8bSMatthew G. Knepley       }
1359ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1360c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1361c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
13629566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
13639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1364846a3e8bSMatthew G. Knepley       }
1365b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1366b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1367846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1368846a3e8bSMatthew G. Knepley         PetscInt val;
13699566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
13709371c9d4SSatish Balay         if (val >= 0) {
13719371c9d4SSatish Balay           color     = lcolors[l % numLColors];
13729371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
13739371c9d4SSatish Balay           break;
13749371c9d4SSatish Balay         }
1375846a3e8bSMatthew G. Knepley       }
1376b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
137763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1378b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
137963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
13801baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1381846a3e8bSMatthew G. Knepley     }
1382b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1383b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
13849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
13859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
13869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
13889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1389552f7358SJed Brown 
1390b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
13919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
13929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
13939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1396b7f6ffafSMatthew G. Knepley 
1397b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
14009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
14019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
14029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1403b7f6ffafSMatthew G. Knepley 
1404b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1405b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1406b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1407b7f6ffafSMatthew G. Knepley 
14089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
14099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
141048a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
14110588280cSMatthew G. Knepley       }
14120588280cSMatthew G. Knepley     }
14139566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
14149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
14159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
141663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
14179566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
14189566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
14199566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
14209566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
14219566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
14220f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
14230f7d6e4aSStefano Zampini     Vec                    cown, acown;
14240f7d6e4aSStefano Zampini     VecScatter             sct;
14250f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
14260f7d6e4aSStefano Zampini     IS                     gid, acis;
14270f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
14280f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
14290f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
14300f7d6e4aSStefano Zampini     const PetscInt        *idxs;
14310f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
14320f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
14330f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
14340f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
14350f7d6e4aSStefano Zampini 
14369566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1438b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
14399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
14400f7d6e4aSStefano Zampini #endif
14410f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
14429566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
14439566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
14440f7d6e4aSStefano Zampini       d1 = 0;
14459566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
14460f7d6e4aSStefano Zampini       nid = d2;
14479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
14489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
14499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
14500f7d6e4aSStefano Zampini     } else nid = 0.0;
14510f7d6e4aSStefano Zampini 
14520f7d6e4aSStefano Zampini     /* Get connectivity */
14539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14549566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
14550f7d6e4aSStefano Zampini 
14560f7d6e4aSStefano Zampini     /* filter overlapped local cells */
14579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
14589566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
14599566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
14609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
14610f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
14620f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
14630f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
14640f7d6e4aSStefano Zampini     }
14659566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
146663a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
14679566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14689566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
14690f7d6e4aSStefano Zampini 
14700f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
14719566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
14729566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
14739566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
14749566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
14750f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
14769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
14779566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
14789566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14799566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
14809566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
14819566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
14829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
14830f7d6e4aSStefano Zampini 
14840f7d6e4aSStefano Zampini     /* compute edgeCut */
14850f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
14869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
14879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
14889566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
14899566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
14909566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
14910f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
14920f7d6e4aSStefano Zampini       PetscInt totl;
14930f7d6e4aSStefano Zampini 
14940f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14959566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14960f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14970f7d6e4aSStefano Zampini         if (work[i] < 0) {
14980f7d6e4aSStefano Zampini           ect += 1;
14990f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
15000f7d6e4aSStefano Zampini         }
15010f7d6e4aSStefano Zampini       }
15020f7d6e4aSStefano Zampini     }
15039566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
15049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
15050f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
15060f7d6e4aSStefano Zampini     lm[1] = -numVertices;
15071c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
150863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0]));
15090f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
15100f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
15110f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
15121c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
151363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1514b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1515f4f49eeaSPierre Jolivet     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.));
15160f7d6e4aSStefano Zampini #else
151763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
15180f7d6e4aSStefano Zampini #endif
15199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
15219566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
15229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1523552f7358SJed Brown   } else {
1524412e9a14SMatthew G. Knepley     const char    *name;
1525d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1526412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1527d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1528ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
15299318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1530412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1531412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1532552f7358SJed Brown 
15339566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
15359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
15369566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
15379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
15389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
153963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
154063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
154163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
15429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
15431c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
15442827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1545d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
15469566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
15479566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1548412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1549412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1550412e9a14SMatthew G. Knepley 
15519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
15529566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1553412e9a14SMatthew G. Knepley       ict = ct0;
15549566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1555412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1556412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1557412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1558412e9a14SMatthew G. Knepley 
15599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1560412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1561412e9a14SMatthew G. Knepley         else ++Nc[1];
1562412e9a14SMatthew G. Knepley       }
1563ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
15649566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15659566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
15669566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
156763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1568834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1569dd400576SPatrick Sanan           if (rank == 0) {
157063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
157163a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
157263a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1573834065abSMatthew G. Knepley           }
1574cbb7f117SMark Adams         }
1575ca7bf7eeSMatthew G. Knepley       } else {
1576ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1577ca7bf7eeSMatthew G. Knepley 
15789371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
15799371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
15809566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15819371c9d4SSatish Balay         locMinMax[0] = Nc[1];
15829371c9d4SSatish Balay         locMinMax[1] = Nc[1];
15839566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1584ca7bf7eeSMatthew G. Knepley         if (d == depth) {
15859371c9d4SSatish Balay           locMinMax[0] = gcNum;
15869371c9d4SSatish Balay           locMinMax[1] = gcNum;
15879566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1588ca7bf7eeSMatthew G. Knepley         }
158963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
15909566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15919566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
15929566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1593ca7bf7eeSMatthew G. Knepley       }
15949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1595552f7358SJed Brown     }
15969566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15979318fe57SMatthew G. Knepley     {
15989318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15999318fe57SMatthew G. Knepley       const PetscReal *L;
16006858538eSMatthew G. Knepley       PetscBool        localized;
16019318fe57SMatthew G. Knepley 
16024fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
16039566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
16046858538eSMatthew G. Knepley       if (L || localized) {
16056858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
16069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
16076858538eSMatthew G. Knepley         if (L) {
16086858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
16099318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
16106858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
16116858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
16129318fe57SMatthew G. Knepley           }
16136858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
16146858538eSMatthew G. Knepley         }
16156858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
16169566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16179318fe57SMatthew G. Knepley       }
16189318fe57SMatthew G. Knepley     }
16199566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
16209566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1621a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1622a57dd577SMatthew G Knepley       DMLabel         label;
1623a57dd577SMatthew G Knepley       const char     *name;
1624a57dd577SMatthew G Knepley       IS              valueIS;
1625a57dd577SMatthew G Knepley       const PetscInt *values;
1626a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1627a57dd577SMatthew G Knepley 
16289566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
16299566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
16309566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
163163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
16329566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
16339566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
16349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1635a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1636a57dd577SMatthew G Knepley         PetscInt size;
1637a57dd577SMatthew G Knepley 
16389566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
16399566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
164063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1641a57dd577SMatthew G Knepley       }
16429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
16439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
16449566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
16459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1646a57dd577SMatthew G Knepley     }
1647c1cad2e7SMatthew G. Knepley     {
1648c1cad2e7SMatthew G. Knepley       char    **labelNames;
1649c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1650c1cad2e7SMatthew G. Knepley       PetscBool flg;
1651c1cad2e7SMatthew G. Knepley 
16529566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
16539566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1654c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1655c1cad2e7SMatthew G. Knepley         DMLabel label;
1656c1cad2e7SMatthew G. Knepley 
16579566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1658c1cad2e7SMatthew G. Knepley         if (flg) {
16599566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
16609566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1661c1cad2e7SMatthew G. Knepley         }
16629566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1663c1cad2e7SMatthew G. Knepley       }
16649566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1665c1cad2e7SMatthew G. Knepley     }
166634aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
166734aa8a36SMatthew G. Knepley     if (dm->Nf) {
166834aa8a36SMatthew G. Knepley       PetscInt f;
166934aa8a36SMatthew G. Knepley 
167034aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
167134aa8a36SMatthew G. Knepley         const char *name;
167234aa8a36SMatthew G. Knepley 
16739566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
16749566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
16759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
16769566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
167734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
16789566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
16799566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
168034aa8a36SMatthew G. Knepley         } else {
16819566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
16829566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
168334aa8a36SMatthew G. Knepley         }
16849566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
168534aa8a36SMatthew G. Knepley       }
168634aa8a36SMatthew G. Knepley     }
16879566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
16888e7ff633SMatthew G. Knepley     if (cdm) {
16899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
16909f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
16919566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
16929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
16938e7ff633SMatthew G. Knepley     }
1694552f7358SJed Brown   }
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696552f7358SJed Brown }
1697552f7358SJed Brown 
1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1699d71ae5a4SJacob Faibussowitsch {
1700e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1701e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1702a12d352dSMatthew G. Knepley   PetscInt       cdim;
1703e5c487bfSMatthew G. Knepley 
1704e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
17069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
17079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1708e5c487bfSMatthew G. Knepley   switch (ct) {
1709a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1710a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1711a12d352dSMatthew G. Knepley     switch (cdim) {
17129371c9d4SSatish Balay     case 1: {
1713a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1714a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1715a12d352dSMatthew G. Knepley 
17169566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
17179566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
17189566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
17199371c9d4SSatish Balay     } break;
17209371c9d4SSatish Balay     case 2: {
1721a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1722a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1723a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1724a12d352dSMatthew G. Knepley 
17259566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17269566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK));
17279566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK));
17289371c9d4SSatish Balay     } break;
1729d71ae5a4SJacob Faibussowitsch     default:
1730d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1731a12d352dSMatthew G. Knepley     }
1732a12d352dSMatthew G. Knepley     break;
1733e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
17349371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17369566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17379566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1738e5c487bfSMatthew G. Knepley     break;
1739e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
17409371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17419371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17439566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17449566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17459566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1746e5c487bfSMatthew G. Knepley     break;
17479f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
17489f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17499f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
17509f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
17519f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
17529f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
17539f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
17549f4ada15SMatthew G. Knepley     break;
1755d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1756d71ae5a4SJacob Faibussowitsch     break;
1757d71ae5a4SJacob Faibussowitsch   default:
1758d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1759e5c487bfSMatthew G. Knepley   }
17603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1761e5c487bfSMatthew G. Knepley }
1762e5c487bfSMatthew G. Knepley 
1763c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1764d71ae5a4SJacob Faibussowitsch {
1765e5c487bfSMatthew G. Knepley   PetscReal   centroid[2] = {0., 0.};
1766e5c487bfSMatthew G. Knepley   PetscMPIInt rank;
1767c5aedaa3SMatthew G. Knepley   PetscInt    fillColor;
1768e5c487bfSMatthew G. Knepley 
1769e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
17709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1771e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1772c5aedaa3SMatthew G. Knepley   for (PetscInt v = 0; v < Nv; ++v) {
1773c5aedaa3SMatthew G. Knepley     centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv;
1774c5aedaa3SMatthew G. Knepley     centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv;
17759371c9d4SSatish Balay   }
1776c5aedaa3SMatthew G. Knepley   for (PetscInt e = 0; e < Nv; ++e) {
1777e5c487bfSMatthew G. Knepley     refCoords[0] = refVertices[e * 2 + 0];
1778e5c487bfSMatthew G. Knepley     refCoords[1] = refVertices[e * 2 + 1];
1779c5aedaa3SMatthew G. Knepley     for (PetscInt d = 1; d <= edgeDiv; ++d) {
1780c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv;
1781c5aedaa3SMatthew G. Knepley       refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv;
1782e5c487bfSMatthew G. Knepley     }
17839566063dSJacob Faibussowitsch     PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1784c5aedaa3SMatthew G. Knepley     for (PetscInt d = 0; d < edgeDiv; ++d) {
17859566063dSJacob Faibussowitsch       PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor));
17869566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK));
1787e5c487bfSMatthew G. Knepley     }
1788e5c487bfSMatthew G. Knepley   }
1789c5aedaa3SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1790c5aedaa3SMatthew G. Knepley }
1791c5aedaa3SMatthew G. Knepley 
1792c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1793c5aedaa3SMatthew G. Knepley {
1794c5aedaa3SMatthew G. Knepley   DMPolytopeType ct;
1795c5aedaa3SMatthew G. Knepley 
1796c5aedaa3SMatthew G. Knepley   PetscFunctionBegin;
1797c5aedaa3SMatthew G. Knepley   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1798c5aedaa3SMatthew G. Knepley   switch (ct) {
1799c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE: {
1800c5aedaa3SMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1801c5aedaa3SMatthew G. Knepley 
1802c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords));
1803c5aedaa3SMatthew G. Knepley   } break;
1804c5aedaa3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: {
1805c5aedaa3SMatthew G. Knepley     PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.};
1806c5aedaa3SMatthew G. Knepley 
1807c5aedaa3SMatthew G. Knepley     PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords));
18089371c9d4SSatish Balay   } break;
1809d71ae5a4SJacob Faibussowitsch   default:
1810d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1811e5c487bfSMatthew G. Knepley   }
18123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1813e5c487bfSMatthew G. Knepley }
1814e5c487bfSMatthew G. Knepley 
1815d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1816d71ae5a4SJacob Faibussowitsch {
1817e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1818e412dcbdSMatthew G. Knepley   DM           cdm;
1819e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1820e412dcbdSMatthew G. Knepley   Vec          coordinates;
1821c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1822e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1823c5aedaa3SMatthew G. Knepley   PetscBool    isnull, drawAffine;
1824c5aedaa3SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv;
1825e412dcbdSMatthew G. Knepley 
1826e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
18279566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
182863a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
1829c5aedaa3SMatthew G. Knepley   PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree));
1830c5aedaa3SMatthew G. Knepley   drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE;
1831c5aedaa3SMatthew G. Knepley   edgeDiv    = cDegree + 1;
18329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
18339566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
18349566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
18359566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
18369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
18379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
18389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1839e412dcbdSMatthew G. Knepley 
18409566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
18419566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
18423ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
18439566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1844e412dcbdSMatthew G. Knepley 
1845c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
18469566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
18479566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1848e412dcbdSMatthew G. Knepley 
1849cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1850cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1851c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1852ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1853c9c77995SMatthew G. Knepley     PetscBool          isDG;
1854cf3064d3SMatthew G. Knepley 
1855c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
18561baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
18571baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1858c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1859cf3064d3SMatthew G. Knepley   }
18609566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
18619566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
18629566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
18639566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
18643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1865e412dcbdSMatthew G. Knepley }
1866e412dcbdSMatthew G. Knepley 
1867e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm)
1868e44f6aebSMatthew G. Knepley {
1869e44f6aebSMatthew G. Knepley   DM           odm = dm, rdm = dm, cdm;
1870e44f6aebSMatthew G. Knepley   PetscFE      fe;
1871e44f6aebSMatthew G. Knepley   PetscSpace   sp;
1872e44f6aebSMatthew G. Knepley   PetscClassId id;
1873e44f6aebSMatthew G. Knepley   PetscInt     degree;
1874e44f6aebSMatthew G. Knepley   PetscBool    hoView = PETSC_TRUE;
1875e44f6aebSMatthew G. Knepley 
1876e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
1877e44f6aebSMatthew G. Knepley   PetscObjectOptionsBegin((PetscObject)dm);
1878e44f6aebSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL));
1879e44f6aebSMatthew G. Knepley   PetscOptionsEnd();
1880e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)dm));
1881e44f6aebSMatthew G. Knepley   *hdm = dm;
1882e44f6aebSMatthew G. Knepley   if (!hoView) PetscFunctionReturn(PETSC_SUCCESS);
1883e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
1884e44f6aebSMatthew G. Knepley   PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe));
1885e44f6aebSMatthew G. Knepley   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
1886e44f6aebSMatthew G. Knepley   if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS);
1887e44f6aebSMatthew G. Knepley   PetscCall(PetscFEGetBasisSpace(fe, &sp));
1888e44f6aebSMatthew G. Knepley   PetscCall(PetscSpaceGetDegree(sp, &degree, NULL));
1889e44f6aebSMatthew G. Knepley   for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) {
1890e44f6aebSMatthew G. Knepley     DM  cdm, rcdm;
1891e44f6aebSMatthew G. Knepley     Mat In;
1892e44f6aebSMatthew G. Knepley     Vec cl, rcl;
1893e44f6aebSMatthew G. Knepley 
1894e44f6aebSMatthew G. Knepley     PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm));
1895c5aedaa3SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL));
1896e44f6aebSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates"));
1897e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(odm, &cdm));
1898e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(rdm, &rcdm));
1899e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(odm, &cl));
1900e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(rdm, &rcl));
1901e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoarseDM(rcdm, cdm));
1902e44f6aebSMatthew G. Knepley     PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL));
1903e44f6aebSMatthew G. Knepley     PetscCall(MatMult(In, cl, rcl));
1904e44f6aebSMatthew G. Knepley     PetscCall(MatDestroy(&In));
1905e44f6aebSMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(rdm, rcl));
1906e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&odm));
1907e44f6aebSMatthew G. Knepley     odm = rdm;
1908e44f6aebSMatthew G. Knepley   }
1909e44f6aebSMatthew G. Knepley   *hdm = rdm;
1910e44f6aebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1911e44f6aebSMatthew G. Knepley }
1912e44f6aebSMatthew G. Knepley 
19131e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19141e50132fSMatthew G. Knepley   #include <exodusII.h>
19156823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
19161e50132fSMatthew G. Knepley #endif
19171e50132fSMatthew G. Knepley 
1918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1919d71ae5a4SJacob Faibussowitsch {
19205f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1921002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1922552f7358SJed Brown 
1923552f7358SJed Brown   PetscFunctionBegin;
1924552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1925552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
19279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
19289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
19319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
19325f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1933552f7358SJed Brown   if (iascii) {
19348135c375SStefano Zampini     PetscViewerFormat format;
19359566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
19361baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
19371baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1938c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1939c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
19409566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1941c6ccd67eSMatthew G. Knepley #else
1942c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1943552f7358SJed Brown #endif
1944e412dcbdSMatthew G. Knepley   } else if (isvtk) {
19459566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1946e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1947e44f6aebSMatthew G. Knepley     DM hdm;
1948e44f6aebSMatthew G. Knepley 
1949e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm));
1950e44f6aebSMatthew G. Knepley     PetscCall(DMPlexView_Draw(hdm, viewer));
1951e44f6aebSMatthew G. Knepley     PetscCall(DMDestroy(&hdm));
19528135c375SStefano Zampini   } else if (isglvis) {
19539566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
19541e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
19551e50132fSMatthew G. Knepley   } else if (isexodus) {
19566823f3c5SBlaise Bourdin     /*
19576823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
19586823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1959da81f932SPierre Jolivet       with ID 1, containing all cells.
19606823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
19616823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
19626823f3c5SBlaise Bourdin     */
19636823f3c5SBlaise Bourdin     PetscInt numCS;
19649566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
19656823f3c5SBlaise Bourdin     if (!numCS) {
19661e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
19679566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
19689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
19699566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
19706823f3c5SBlaise Bourdin     }
19719566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
19721e50132fSMatthew G. Knepley #endif
19735f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
19745f34f2dcSJed Brown   } else if (iscgns) {
19755f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
19765f34f2dcSJed Brown #endif
19771baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1978cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
19799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1980cb3ba0daSMatthew G. Knepley   if (flg) {
1981cb3ba0daSMatthew G. Knepley     Vec ranks;
19829566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
19839566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
19849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1985cb3ba0daSMatthew G. Knepley   }
1986002a2709SMatthew G. Knepley   /* Optionally view a label */
19879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1988002a2709SMatthew G. Knepley   if (flg) {
1989002a2709SMatthew G. Knepley     DMLabel label;
1990002a2709SMatthew G. Knepley     Vec     val;
1991002a2709SMatthew G. Knepley 
19929566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
199328b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
19949566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
19959566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
19969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1997002a2709SMatthew G. Knepley   }
19983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1999552f7358SJed Brown }
2000552f7358SJed Brown 
20017f96f51bSksagiyam /*@
2002a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
20037f96f51bSksagiyam 
200420f4b53cSBarry Smith   Collective
20057f96f51bSksagiyam 
20067f96f51bSksagiyam   Input Parameters:
2007a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
2008a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
20097f96f51bSksagiyam 
20107f96f51bSksagiyam   Level: advanced
20117f96f51bSksagiyam 
20121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
20137f96f51bSksagiyam @*/
2014d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
2015d71ae5a4SJacob Faibussowitsch {
20167f96f51bSksagiyam   PetscBool ishdf5;
20177f96f51bSksagiyam 
20187f96f51bSksagiyam   PetscFunctionBegin;
20197f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20207f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
20237f96f51bSksagiyam   if (ishdf5) {
20247f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
20257f96f51bSksagiyam     PetscViewerFormat format;
20269566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20277f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20287f96f51bSksagiyam       IS globalPointNumbering;
20297f96f51bSksagiyam 
20309566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
20319566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
20329566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
203398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
20347f96f51bSksagiyam #else
20357f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20367f96f51bSksagiyam #endif
20377f96f51bSksagiyam   }
20389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
20393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20407f96f51bSksagiyam }
20417f96f51bSksagiyam 
204277b8e257Sksagiyam /*@
2043a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
204477b8e257Sksagiyam 
204520f4b53cSBarry Smith   Collective
204677b8e257Sksagiyam 
204777b8e257Sksagiyam   Input Parameters:
2048a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
2049a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
205077b8e257Sksagiyam 
205177b8e257Sksagiyam   Level: advanced
205277b8e257Sksagiyam 
20531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
205477b8e257Sksagiyam @*/
2055d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
2056d71ae5a4SJacob Faibussowitsch {
205777b8e257Sksagiyam   PetscBool ishdf5;
205877b8e257Sksagiyam 
205977b8e257Sksagiyam   PetscFunctionBegin;
206077b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
206177b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
206477b8e257Sksagiyam   if (ishdf5) {
206577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
206677b8e257Sksagiyam     PetscViewerFormat format;
20679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
206877b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20699566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
2070fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
207177b8e257Sksagiyam #else
207277b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
207377b8e257Sksagiyam #endif
207477b8e257Sksagiyam   }
20759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
20763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207777b8e257Sksagiyam }
207877b8e257Sksagiyam 
2079bd6565f1Sksagiyam /*@
2080a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
2081bd6565f1Sksagiyam 
208220f4b53cSBarry Smith   Collective
2083bd6565f1Sksagiyam 
2084bd6565f1Sksagiyam   Input Parameters:
2085a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
2086a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
2087bd6565f1Sksagiyam 
2088bd6565f1Sksagiyam   Level: advanced
2089bd6565f1Sksagiyam 
20901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
2091bd6565f1Sksagiyam @*/
2092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
2093d71ae5a4SJacob Faibussowitsch {
2094bd6565f1Sksagiyam   PetscBool ishdf5;
2095bd6565f1Sksagiyam 
2096bd6565f1Sksagiyam   PetscFunctionBegin;
2097bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2098bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
2101bd6565f1Sksagiyam   if (ishdf5) {
2102bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
2103bd6565f1Sksagiyam     IS                globalPointNumbering;
2104bd6565f1Sksagiyam     PetscViewerFormat format;
2105bd6565f1Sksagiyam 
21069566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2107bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21089566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
21099566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
21109566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
211198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2112bd6565f1Sksagiyam #else
2113bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2114bd6565f1Sksagiyam #endif
2115bd6565f1Sksagiyam   }
21169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
21173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2118bd6565f1Sksagiyam }
2119bd6565f1Sksagiyam 
2120021affd3Sksagiyam /*@
2121a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
2122021affd3Sksagiyam 
212320f4b53cSBarry Smith   Collective
2124021affd3Sksagiyam 
2125021affd3Sksagiyam   Input Parameters:
2126a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
2127a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
21280318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL`
2129021affd3Sksagiyam 
2130021affd3Sksagiyam   Level: advanced
2131021affd3Sksagiyam 
2132021affd3Sksagiyam   Notes:
2133420bcc1bSBarry Smith   This function is a wrapper around `PetscSectionView()`; in addition to the raw section, it saves information that associates the section points to the topology (`dm`) points. When the topology (`dm`) and the section are later loaded with `DMPlexTopologyLoad()` and `DMPlexSectionLoad()`, respectively, this information is used to match section points with topology points.
2134021affd3Sksagiyam 
21350318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2136021affd3Sksagiyam 
21371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
2138021affd3Sksagiyam @*/
2139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
2140d71ae5a4SJacob Faibussowitsch {
2141021affd3Sksagiyam   PetscBool ishdf5;
2142021affd3Sksagiyam 
2143021affd3Sksagiyam   PetscFunctionBegin;
2144021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2145021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21460318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2147021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
2150021affd3Sksagiyam   if (ishdf5) {
2151021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
21529566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
2153021affd3Sksagiyam #else
2154021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2155021affd3Sksagiyam #endif
2156021affd3Sksagiyam   }
21579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
21583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2159021affd3Sksagiyam }
2160021affd3Sksagiyam 
21613e97647fSksagiyam /*@
21623e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
21633e97647fSksagiyam 
216420f4b53cSBarry Smith   Collective
21653e97647fSksagiyam 
21663e97647fSksagiyam   Input Parameters:
2167a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2168a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
21690318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
21703e97647fSksagiyam - vec       - The global vector to be saved
21713e97647fSksagiyam 
21723e97647fSksagiyam   Level: advanced
21733e97647fSksagiyam 
21743e97647fSksagiyam   Notes:
21750318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
21763e97647fSksagiyam 
217760225df5SJacob Faibussowitsch   Calling sequence:
2178a1cb98faSBarry Smith .vb
2179a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2180a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2181a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2182a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2183a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2184a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2185a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2186a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2187a1cb98faSBarry Smith        PetscSectionSetUp(section);
2188a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2189a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2190a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2191a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2192a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2193a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2194a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2195a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2196a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2197a1cb98faSBarry Smith        DMDestroy(&dm);
2198a1cb98faSBarry Smith .ve
21993e97647fSksagiyam 
22001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22013e97647fSksagiyam @*/
2202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2203d71ae5a4SJacob Faibussowitsch {
22043e97647fSksagiyam   PetscBool ishdf5;
22053e97647fSksagiyam 
22063e97647fSksagiyam   PetscFunctionBegin;
22073e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22083e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22090318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22103e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22113e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22123e97647fSksagiyam   /* Check consistency */
22133e97647fSksagiyam   {
22143e97647fSksagiyam     PetscSection section;
22153e97647fSksagiyam     PetscBool    includesConstraints;
22163e97647fSksagiyam     PetscInt     m, m1;
22173e97647fSksagiyam 
22189566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22199566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
22209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22219566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22229566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
222363a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
22243e97647fSksagiyam   }
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22273e97647fSksagiyam   if (ishdf5) {
22283e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
22299566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
22303e97647fSksagiyam #else
22313e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22323e97647fSksagiyam #endif
22333e97647fSksagiyam   }
22349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
22353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22363e97647fSksagiyam }
22373e97647fSksagiyam 
22383e97647fSksagiyam /*@
22393e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
22403e97647fSksagiyam 
224120f4b53cSBarry Smith   Collective
22423e97647fSksagiyam 
22433e97647fSksagiyam   Input Parameters:
2244a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2245a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
22460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL`
22473e97647fSksagiyam - vec       - The local vector to be saved
22483e97647fSksagiyam 
22493e97647fSksagiyam   Level: advanced
22503e97647fSksagiyam 
2251a1cb98faSBarry Smith   Note:
22520318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
22533e97647fSksagiyam 
225460225df5SJacob Faibussowitsch   Calling sequence:
2255a1cb98faSBarry Smith .vb
2256a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2257a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2258a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2259a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2260a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2261a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2262a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2263a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2264a1cb98faSBarry Smith        PetscSectionSetUp(section);
2265a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2266a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2267a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2268a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2269a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2270a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2271a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2272a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2273a1cb98faSBarry Smith        DMDestroy(&dm);
2274a1cb98faSBarry Smith .ve
22753e97647fSksagiyam 
22761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
22773e97647fSksagiyam @*/
2278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2279d71ae5a4SJacob Faibussowitsch {
22803e97647fSksagiyam   PetscBool ishdf5;
22813e97647fSksagiyam 
22823e97647fSksagiyam   PetscFunctionBegin;
22833e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22843e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22850318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
22863e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22873e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
22883e97647fSksagiyam   /* Check consistency */
22893e97647fSksagiyam   {
22903e97647fSksagiyam     PetscSection section;
22913e97647fSksagiyam     PetscBool    includesConstraints;
22923e97647fSksagiyam     PetscInt     m, m1;
22933e97647fSksagiyam 
22949566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
22959566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
22969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
22979566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
22989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
229963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
23003e97647fSksagiyam   }
23019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23033e97647fSksagiyam   if (ishdf5) {
23043e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
23059566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
23063e97647fSksagiyam #else
23073e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23083e97647fSksagiyam #endif
23093e97647fSksagiyam   }
23109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
23113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23123e97647fSksagiyam }
23133e97647fSksagiyam 
2314d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2315d71ae5a4SJacob Faibussowitsch {
2316d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
23172c40f234SMatthew G. Knepley 
23182c40f234SMatthew G. Knepley   PetscFunctionBegin;
23192c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23202c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2322d4f5a9a0SVaclav Hapla   if (ishdf5) {
23232c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
23249c48423bSVaclav Hapla     PetscViewerFormat format;
23259566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
23269c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
23279566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2328509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23299566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
233098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
23313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
23322c40f234SMatthew G. Knepley #else
23332c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2334552f7358SJed Brown #endif
233598921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2336552f7358SJed Brown }
2337552f7358SJed Brown 
2338ea8e1828Sksagiyam /*@
2339a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2340ea8e1828Sksagiyam 
234120f4b53cSBarry Smith   Collective
2342ea8e1828Sksagiyam 
2343ea8e1828Sksagiyam   Input Parameters:
2344a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2345a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2346ea8e1828Sksagiyam 
23472fe279fdSBarry Smith   Output Parameter:
234820f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded
2349dec9e869Sksagiyam 
2350ea8e1828Sksagiyam   Level: advanced
2351ea8e1828Sksagiyam 
23521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2353a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2354ea8e1828Sksagiyam @*/
2355d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2356d71ae5a4SJacob Faibussowitsch {
2357ea8e1828Sksagiyam   PetscBool ishdf5;
2358ea8e1828Sksagiyam 
2359ea8e1828Sksagiyam   PetscFunctionBegin;
2360ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2361ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23624f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
23639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2365ea8e1828Sksagiyam   if (ishdf5) {
2366ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2367ea8e1828Sksagiyam     PetscViewerFormat format;
23689566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2369ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
23709566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
237198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2372ea8e1828Sksagiyam #else
2373ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2374ea8e1828Sksagiyam #endif
2375ea8e1828Sksagiyam   }
23769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
23773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2378ea8e1828Sksagiyam }
2379ea8e1828Sksagiyam 
23803e701f1cSksagiyam /*@
2381a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
23823e701f1cSksagiyam 
238320f4b53cSBarry Smith   Collective
23843e701f1cSksagiyam 
23853e701f1cSksagiyam   Input Parameters:
2386a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2387a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2388a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
23893e701f1cSksagiyam 
23903e701f1cSksagiyam   Level: advanced
23913e701f1cSksagiyam 
23921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2393a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
23943e701f1cSksagiyam @*/
2395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2396d71ae5a4SJacob Faibussowitsch {
23973e701f1cSksagiyam   PetscBool ishdf5;
23983e701f1cSksagiyam 
23993e701f1cSksagiyam   PetscFunctionBegin;
24003e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24013e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2402c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24053e701f1cSksagiyam   if (ishdf5) {
24063e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
24073e701f1cSksagiyam     PetscViewerFormat format;
24089566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
24093e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24109566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
241198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
24123e701f1cSksagiyam #else
24133e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24143e701f1cSksagiyam #endif
24153e701f1cSksagiyam   }
24169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
24173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24183e701f1cSksagiyam }
24193e701f1cSksagiyam 
2420b08ad5deSksagiyam /*@
2421a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2422b08ad5deSksagiyam 
242320f4b53cSBarry Smith   Collective
2424b08ad5deSksagiyam 
2425b08ad5deSksagiyam   Input Parameters:
2426a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2427a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
242820f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2429b08ad5deSksagiyam 
2430b08ad5deSksagiyam   Level: advanced
2431b08ad5deSksagiyam 
2432a1cb98faSBarry Smith   Note:
2433a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2434e6368b79SVaclav Hapla 
24351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2436a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2437b08ad5deSksagiyam @*/
2438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2439d71ae5a4SJacob Faibussowitsch {
2440b08ad5deSksagiyam   PetscBool ishdf5;
2441b08ad5deSksagiyam 
2442b08ad5deSksagiyam   PetscFunctionBegin;
2443b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2444b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2445e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
24469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2448b08ad5deSksagiyam   if (ishdf5) {
2449b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2450b08ad5deSksagiyam     PetscViewerFormat format;
2451b08ad5deSksagiyam 
24529566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2453b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
24549566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
245598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2456b08ad5deSksagiyam #else
2457b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2458b08ad5deSksagiyam #endif
2459b08ad5deSksagiyam   }
24609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
24613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2462b08ad5deSksagiyam }
2463b08ad5deSksagiyam 
2464f84dd6b4Sksagiyam /*@
2465a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2466f84dd6b4Sksagiyam 
246720f4b53cSBarry Smith   Collective
2468f84dd6b4Sksagiyam 
2469f84dd6b4Sksagiyam   Input Parameters:
2470a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2471a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
24720318f8a0SStefano Zampini . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL`
2473a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2474f84dd6b4Sksagiyam 
2475a4e35b19SJacob Faibussowitsch   Output Parameters:
247620f4b53cSBarry Smith + globalDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a global `Vec` associated with the `sectiondm`'s global section (`NULL` if not needed)
247720f4b53cSBarry Smith - localDofSF  - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a local `Vec` associated with the `sectiondm`'s local section (`NULL` if not needed)
2478f84dd6b4Sksagiyam 
2479f84dd6b4Sksagiyam   Level: advanced
2480f84dd6b4Sksagiyam 
2481f84dd6b4Sksagiyam   Notes:
248220f4b53cSBarry Smith   This function is a wrapper around `PetscSectionLoad()`; it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in `dm`. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points.
2483f84dd6b4Sksagiyam 
24840318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2485f84dd6b4Sksagiyam 
248620f4b53cSBarry Smith   The output parameter, `globalDofSF` (`localDofSF`), can later be used with `DMPlexGlobalVectorLoad()` (`DMPlexLocalVectorLoad()`) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section.
2487f84dd6b4Sksagiyam 
2488f84dd6b4Sksagiyam   Example using 2 processes:
2489a1cb98faSBarry Smith .vb
2490a1cb98faSBarry Smith   NX (number of points on dm): 4
2491a1cb98faSBarry Smith   sectionA                   : the on-disk section
2492a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2493a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2494a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2495a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2496f84dd6b4Sksagiyam 
2497a1cb98faSBarry Smith                                      rank 0    rank 1
2498a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2499a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2500a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2501a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2502a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2503a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2504a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2505a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2506a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2507a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2508a1cb98faSBarry Smith .ve
2509a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2510a1cb98faSBarry Smith 
25111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2512f84dd6b4Sksagiyam @*/
2513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2514d71ae5a4SJacob Faibussowitsch {
2515f84dd6b4Sksagiyam   PetscBool ishdf5;
2516f84dd6b4Sksagiyam 
2517f84dd6b4Sksagiyam   PetscFunctionBegin;
2518f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2519f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25200318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
2521f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2522f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
25234f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
25244f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
25259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2527f84dd6b4Sksagiyam   if (ishdf5) {
2528f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
25299566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2530f84dd6b4Sksagiyam #else
2531f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2532f84dd6b4Sksagiyam #endif
2533f84dd6b4Sksagiyam   }
25349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
25353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2536f84dd6b4Sksagiyam }
2537f84dd6b4Sksagiyam 
25388be3dfe1Sksagiyam /*@
25398be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
25408be3dfe1Sksagiyam 
254120f4b53cSBarry Smith   Collective
25428be3dfe1Sksagiyam 
25438be3dfe1Sksagiyam   Input Parameters:
2544a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2545a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
25460318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL`
2547a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
25488be3dfe1Sksagiyam - vec       - The global vector to set values of
25498be3dfe1Sksagiyam 
25508be3dfe1Sksagiyam   Level: advanced
25518be3dfe1Sksagiyam 
25528be3dfe1Sksagiyam   Notes:
25530318f8a0SStefano Zampini   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
25548be3dfe1Sksagiyam 
255560225df5SJacob Faibussowitsch   Calling sequence:
2556a1cb98faSBarry Smith .vb
2557a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2558a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2559a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2560a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2561a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2562a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2563a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2564a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2565a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2566a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2567a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2568a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2569a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2570a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2571a1cb98faSBarry Smith        DMDestroy(&dm);
2572a1cb98faSBarry Smith .ve
25738be3dfe1Sksagiyam 
25741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2575a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
25768be3dfe1Sksagiyam @*/
2577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2578d71ae5a4SJacob Faibussowitsch {
25798be3dfe1Sksagiyam   PetscBool ishdf5;
25808be3dfe1Sksagiyam 
25818be3dfe1Sksagiyam   PetscFunctionBegin;
25828be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25838be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
25840318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
25858be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
25868be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
25878be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
25888be3dfe1Sksagiyam   /* Check consistency */
25898be3dfe1Sksagiyam   {
25908be3dfe1Sksagiyam     PetscSection section;
25918be3dfe1Sksagiyam     PetscBool    includesConstraints;
25928be3dfe1Sksagiyam     PetscInt     m, m1;
25938be3dfe1Sksagiyam 
25949566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25959566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
25969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25979566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
259963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
26008be3dfe1Sksagiyam   }
26019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26038be3dfe1Sksagiyam   if (ishdf5) {
26048be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26059566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26068be3dfe1Sksagiyam #else
26078be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26088be3dfe1Sksagiyam #endif
26098be3dfe1Sksagiyam   }
26109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
26113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26128be3dfe1Sksagiyam }
26138be3dfe1Sksagiyam 
26148be3dfe1Sksagiyam /*@
26158be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
26168be3dfe1Sksagiyam 
261720f4b53cSBarry Smith   Collective
26188be3dfe1Sksagiyam 
26198be3dfe1Sksagiyam   Input Parameters:
2620a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2621a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
26220318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL`
2623a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
26248be3dfe1Sksagiyam - vec       - The local vector to set values of
26258be3dfe1Sksagiyam 
26268be3dfe1Sksagiyam   Level: advanced
26278be3dfe1Sksagiyam 
26288be3dfe1Sksagiyam   Notes:
26290318f8a0SStefano Zampini   In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
26308be3dfe1Sksagiyam 
263160225df5SJacob Faibussowitsch   Calling sequence:
2632a1cb98faSBarry Smith .vb
2633a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2634a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2635a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2636a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2637a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2638a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2639a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2640a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2641a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2642a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2643a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2644a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2645a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2646a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2647a1cb98faSBarry Smith        DMDestroy(&dm);
2648a1cb98faSBarry Smith .ve
26498be3dfe1Sksagiyam 
26501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2651a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
26528be3dfe1Sksagiyam @*/
2653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2654d71ae5a4SJacob Faibussowitsch {
26558be3dfe1Sksagiyam   PetscBool ishdf5;
26568be3dfe1Sksagiyam 
26578be3dfe1Sksagiyam   PetscFunctionBegin;
26588be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26598be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
26600318f8a0SStefano Zampini   if (!sectiondm) sectiondm = dm;
26618be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
26628be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
26638be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
26648be3dfe1Sksagiyam   /* Check consistency */
26658be3dfe1Sksagiyam   {
26668be3dfe1Sksagiyam     PetscSection section;
26678be3dfe1Sksagiyam     PetscBool    includesConstraints;
26688be3dfe1Sksagiyam     PetscInt     m, m1;
26698be3dfe1Sksagiyam 
26709566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
26719566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
26729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
26739566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
26749566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
267563a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
26768be3dfe1Sksagiyam   }
26779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
26789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26798be3dfe1Sksagiyam   if (ishdf5) {
26808be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
26819566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
26828be3dfe1Sksagiyam #else
26838be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
26848be3dfe1Sksagiyam #endif
26858be3dfe1Sksagiyam   }
26869566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
26873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26888be3dfe1Sksagiyam }
26898be3dfe1Sksagiyam 
2690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2691d71ae5a4SJacob Faibussowitsch {
2692552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2693552f7358SJed Brown 
2694552f7358SJed Brown   PetscFunctionBegin;
26959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
26969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
26979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
26989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
26996c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL));
27002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
27012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
27022e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
27032e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
27046bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
27056bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2706adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL));
2707adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL));
2708adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL));
2709adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL));
2710c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2711c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
2712d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL));
2713d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL));
27145f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
27153ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
27169566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
27179566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
27189566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
27199566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
27209566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
27219566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
272221027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27239f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
27249566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
27259566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
27269566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
27271d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
27289566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
27299566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
27309566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
27319566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
27329566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
27334e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
27346725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
27356725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
27369566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
27379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
27389566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
27399566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
27409566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
27419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
27429566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
27439566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
27449566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
27459566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
27469566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2747552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
27489566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
27493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2750552f7358SJed Brown }
2751552f7358SJed Brown 
2752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2753d71ae5a4SJacob Faibussowitsch {
2754d02c7345SMatthew G. Knepley   PetscSection           sectionGlobal, sectionLocal;
2755acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
27569fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2757837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2758b412c318SBarry Smith   MatType                mtype;
27591428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2760552f7358SJed Brown 
2761552f7358SJed Brown   PetscFunctionBegin;
27629566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2763b412c318SBarry Smith   mtype = dm->mattype;
2764d02c7345SMatthew G. Knepley   PetscCall(DMGetLocalSection(dm, &sectionLocal));
27659566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
27669566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
27679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
27689fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
27699566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
27709566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
27719566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
27729566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
27739566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2774acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
27759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
27769566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
27779566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
27789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
27799566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
27809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
27819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
27829566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2783552f7358SJed Brown   if (!isShell) {
2784837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
27859fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2786863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2787552f7358SJed Brown 
27889566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
27899fca9976SJed Brown 
27909fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
27919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2792863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2793e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2794863027abSJed Brown       switch (dm->blocking_type) {
27950e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
27969fca9976SJed Brown         PetscInt bdof, offset;
2797a9d99c84SMatthew G. Knepley 
27989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
27999fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
28009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
2801d02c7345SMatthew G. Knepley         for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof;
2802d02c7345SMatthew G. Knepley         // Signal block concatenation
2803d02c7345SMatthew G. Knepley         if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof);
28041d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
28051d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
28061d17a0a3SMatthew G. Knepley         if (dof) {
28079371c9d4SSatish Balay           if (bs < 0) {
28089371c9d4SSatish Balay             bs = bdof;
28099371c9d4SSatish Balay           } else if (bs != bdof) {
28109371c9d4SSatish Balay             bs = 1;
28119371c9d4SSatish Balay           }
2812552f7358SJed Brown         }
2813863027abSJed Brown       } break;
2814863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2815863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2816863027abSJed Brown           PetscInt num_comp, bdof, offset;
2817863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2818863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2819863027abSJed Brown           if (dof < 0) continue;
2820863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2821863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2822863027abSJed 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);
2823863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2824863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2825863027abSJed Brown           // Handle possibly constant block size (unlikely)
2826863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2827863027abSJed Brown           if (dof) {
2828863027abSJed Brown             if (bs < 0) {
2829863027abSJed Brown               bs = bdof;
2830863027abSJed Brown             } else if (bs != bdof) {
2831863027abSJed Brown               bs = 1;
2832863027abSJed Brown             }
2833863027abSJed Brown           }
2834863027abSJed Brown         }
2835863027abSJed Brown       } break;
2836863027abSJed Brown       }
28372a28c762SMatthew G Knepley     }
28382a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2839e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2840e432b41dSStefano Zampini     bsLocal[1] = bs;
28419566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2842e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2843e432b41dSStefano Zampini     else bs = bsMinMax[0];
28446fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
28459566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
28460682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
28479566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
28489566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
28490682b8bbSJed Brown     } else {
28509566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
28519566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
28529566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2853552f7358SJed Brown     }
28549fca9976SJed Brown     { // Consolidate blocks
28559fca9976SJed Brown       PetscInt nblocks = 0;
28569fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
28579fca9976SJed Brown         if (pblocks[i] == 0) continue;
2858d02c7345SMatthew G. Knepley         // Negative block size indicates the blocks should be concatenated
2859d02c7345SMatthew G. Knepley         if (pblocks[i] < 0) {
2860d02c7345SMatthew G. Knepley           pblocks[i] = -pblocks[i];
2861d02c7345SMatthew G. Knepley           pblocks[nblocks - 1] += pblocks[i];
2862d02c7345SMatthew G. Knepley         } else {
28639fca9976SJed Brown           pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2864d02c7345SMatthew G. Knepley         }
2865ad540459SPierre 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]);
28669fca9976SJed Brown       }
28679fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
28689fca9976SJed Brown     }
28699fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2870aa0f6e3cSJed Brown   }
28719566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
28723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2873552f7358SJed Brown }
2874552f7358SJed Brown 
28757cd05799SMatthew G. Knepley /*@
2876a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2877be36d101SStefano Zampini 
2878a1cb98faSBarry Smith   Not Collective
2879be36d101SStefano Zampini 
2880be36d101SStefano Zampini   Input Parameter:
288160225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2882be36d101SStefano Zampini 
28832fe279fdSBarry Smith   Output Parameter:
2884be36d101SStefano Zampini . subsection - The subdomain section
2885be36d101SStefano Zampini 
2886be36d101SStefano Zampini   Level: developer
2887be36d101SStefano Zampini 
28881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
28897cd05799SMatthew G. Knepley @*/
2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2891d71ae5a4SJacob Faibussowitsch {
2892be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2893be36d101SStefano Zampini 
2894be36d101SStefano Zampini   PetscFunctionBegin;
2895be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2896be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2897be36d101SStefano Zampini     PetscSection section;
2898be36d101SStefano Zampini     PetscSF      sf;
2899be36d101SStefano Zampini 
29009566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
29019566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
2902eb9d3e4dSMatthew G. Knepley     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
29039566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2904be36d101SStefano Zampini   }
2905be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
29063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2907be36d101SStefano Zampini }
2908be36d101SStefano Zampini 
2909552f7358SJed Brown /*@
291020f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2911552f7358SJed Brown 
2912a1cb98faSBarry Smith   Not Collective
2913552f7358SJed Brown 
2914552f7358SJed Brown   Input Parameter:
291560225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2916552f7358SJed Brown 
2917552f7358SJed Brown   Output Parameters:
2918552f7358SJed Brown + pStart - The first mesh point
2919552f7358SJed Brown - pEnd   - The upper bound for mesh points
2920552f7358SJed Brown 
2921552f7358SJed Brown   Level: beginner
2922552f7358SJed Brown 
29231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2924552f7358SJed Brown @*/
2925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2926d71ae5a4SJacob Faibussowitsch {
2927552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2928552f7358SJed Brown 
2929552f7358SJed Brown   PetscFunctionBegin;
2930552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29319f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
29329f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
29333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2934552f7358SJed Brown }
2935552f7358SJed Brown 
2936552f7358SJed Brown /*@
293720f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2938552f7358SJed Brown 
2939a1cb98faSBarry Smith   Not Collective
2940552f7358SJed Brown 
2941552f7358SJed Brown   Input Parameters:
294260225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2943552f7358SJed Brown . pStart - The first mesh point
2944552f7358SJed Brown - pEnd   - The upper bound for mesh points
2945552f7358SJed Brown 
2946552f7358SJed Brown   Level: beginner
2947552f7358SJed Brown 
29481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2949552f7358SJed Brown @*/
2950d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2951d71ae5a4SJacob Faibussowitsch {
2952552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2953552f7358SJed Brown 
2954552f7358SJed Brown   PetscFunctionBegin;
2955552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29569566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
29579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
295821027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
29593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2960552f7358SJed Brown }
2961552f7358SJed Brown 
2962552f7358SJed Brown /*@
2963eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2964552f7358SJed Brown 
2965a1cb98faSBarry Smith   Not Collective
2966552f7358SJed Brown 
2967552f7358SJed Brown   Input Parameters:
296860225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2969a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2970552f7358SJed Brown 
2971552f7358SJed Brown   Output Parameter:
297220f4b53cSBarry Smith . size - The cone size for point `p`
2973552f7358SJed Brown 
2974552f7358SJed Brown   Level: beginner
2975552f7358SJed Brown 
29761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2977552f7358SJed Brown @*/
2978d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2979d71ae5a4SJacob Faibussowitsch {
2980552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2981552f7358SJed Brown 
2982552f7358SJed Brown   PetscFunctionBegin;
2983552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
29844f572ea9SToby Isaac   PetscAssertPointer(size, 3);
29859f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
29869f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
29873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2988552f7358SJed Brown }
2989552f7358SJed Brown 
2990552f7358SJed Brown /*@
2991eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2992552f7358SJed Brown 
2993a1cb98faSBarry Smith   Not Collective
2994552f7358SJed Brown 
2995552f7358SJed Brown   Input Parameters:
299660225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
2997a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
299820f4b53cSBarry Smith - size - The cone size for point `p`
2999552f7358SJed Brown 
3000552f7358SJed Brown   Level: beginner
3001552f7358SJed Brown 
3002a1cb98faSBarry Smith   Note:
3003a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
3004a1cb98faSBarry Smith 
30051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
3006552f7358SJed Brown @*/
3007d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
3008d71ae5a4SJacob Faibussowitsch {
3009552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3010552f7358SJed Brown 
3011552f7358SJed Brown   PetscFunctionBegin;
3012552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30139f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
30149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
30153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3016552f7358SJed Brown }
3017552f7358SJed Brown 
3018552f7358SJed Brown /*@C
3019eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
3020552f7358SJed Brown 
3021a1cb98faSBarry Smith   Not Collective
3022552f7358SJed Brown 
3023552f7358SJed Brown   Input Parameters:
3024a1cb98faSBarry Smith + dm - The `DMPLEX`
3025a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3026552f7358SJed Brown 
3027552f7358SJed Brown   Output Parameter:
302820f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
3029552f7358SJed Brown 
3030552f7358SJed Brown   Level: beginner
3031552f7358SJed Brown 
303260225df5SJacob Faibussowitsch   Fortran Notes:
3033a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
3034a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
30353813dfbdSMatthew G Knepley 
30361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
3037552f7358SJed Brown @*/
3038d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
3039d71ae5a4SJacob Faibussowitsch {
3040552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3041552f7358SJed Brown   PetscInt off;
3042552f7358SJed Brown 
3043552f7358SJed Brown   PetscFunctionBegin;
3044552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30454f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
30469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30478e3a54c0SPierre Jolivet   *cone = PetscSafePointerPlusOffset(mesh->cones, off);
30483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3049552f7358SJed Brown }
3050552f7358SJed Brown 
30510ce7577fSVaclav Hapla /*@C
30520ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
30530ce7577fSVaclav Hapla 
3054a1cb98faSBarry Smith   Not Collective
30550ce7577fSVaclav Hapla 
30560ce7577fSVaclav Hapla   Input Parameters:
3057a1cb98faSBarry Smith + dm - The `DMPLEX`
3058a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
30590ce7577fSVaclav Hapla 
3060d8d19677SJose E. Roman   Output Parameters:
306120f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
306220f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
30630ce7577fSVaclav Hapla 
30640ce7577fSVaclav Hapla   Level: intermediate
30650ce7577fSVaclav Hapla 
30661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
30670ce7577fSVaclav Hapla @*/
3068d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
3069d71ae5a4SJacob Faibussowitsch {
30700ce7577fSVaclav Hapla   PetscSection cs, newcs;
30710ce7577fSVaclav Hapla   PetscInt    *cones;
30720ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
30730ce7577fSVaclav Hapla   PetscInt     n;
30740ce7577fSVaclav Hapla 
30750ce7577fSVaclav Hapla   PetscFunctionBegin;
30769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
30779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
30789566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
30790ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
30800ce7577fSVaclav Hapla   if (pCones) {
30819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
30829566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
30830ce7577fSVaclav Hapla   }
30843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30850ce7577fSVaclav Hapla }
30860ce7577fSVaclav Hapla 
3087af9eab45SVaclav Hapla /*@
3088af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
3089d4636a37SVaclav Hapla 
3090a1cb98faSBarry Smith   Not Collective
3091d4636a37SVaclav Hapla 
3092d4636a37SVaclav Hapla   Input Parameters:
3093a1cb98faSBarry Smith + dm     - The `DMPLEX`
3094a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3095d4636a37SVaclav Hapla 
3096d4636a37SVaclav Hapla   Output Parameter:
3097af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
3098d4636a37SVaclav Hapla 
3099d4636a37SVaclav Hapla   Level: advanced
3100d4636a37SVaclav Hapla 
3101af9eab45SVaclav Hapla   Notes:
310220f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
3103af9eab45SVaclav Hapla 
3104a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
3105a1cb98faSBarry Smith 
31061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
3107a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
3108d4636a37SVaclav Hapla @*/
3109d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
3110d71ae5a4SJacob Faibussowitsch {
3111af9eab45SVaclav Hapla   IS      *expandedPointsAll;
3112af9eab45SVaclav Hapla   PetscInt depth;
3113d4636a37SVaclav Hapla 
3114d4636a37SVaclav Hapla   PetscFunctionBegin;
3115af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3116af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31174f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
31189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
3119af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
31209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
31219566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
31223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3123af9eab45SVaclav Hapla }
3124af9eab45SVaclav Hapla 
3125af9eab45SVaclav Hapla /*@
3126af9eab45SVaclav 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).
3127af9eab45SVaclav Hapla 
3128a1cb98faSBarry Smith   Not Collective
3129af9eab45SVaclav Hapla 
3130af9eab45SVaclav Hapla   Input Parameters:
3131a1cb98faSBarry Smith + dm     - The `DMPLEX`
3132a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3133af9eab45SVaclav Hapla 
3134d8d19677SJose E. Roman   Output Parameters:
3135a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3136af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
3137af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3138af9eab45SVaclav Hapla 
3139af9eab45SVaclav Hapla   Level: advanced
3140af9eab45SVaclav Hapla 
3141af9eab45SVaclav Hapla   Notes:
3142a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
3143af9eab45SVaclav Hapla 
3144a4e35b19SJacob 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.
3145af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
3146af9eab45SVaclav Hapla 
3147a4e35b19SJacob 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\:
3148a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
3149a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
3150af9eab45SVaclav Hapla 
31511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3152a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
3153af9eab45SVaclav Hapla @*/
3154d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3155d71ae5a4SJacob Faibussowitsch {
3156af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
3157af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
3158af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
3159af9eab45SVaclav Hapla   IS             *expandedPoints_;
3160af9eab45SVaclav Hapla   PetscSection   *sections_;
3161af9eab45SVaclav Hapla 
3162af9eab45SVaclav Hapla   PetscFunctionBegin;
3163af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3164af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
31654f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
31664f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
31674f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
31689566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
31699566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
31709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
31719566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
31729566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
3173af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
3174af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
31759566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
31769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
3177af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
3179af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
31809566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
31819566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3182af9eab45SVaclav Hapla       } else {
31839566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3184af9eab45SVaclav Hapla       }
3185af9eab45SVaclav Hapla     }
31869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
31879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
31889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3189af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
31909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
31919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3192af9eab45SVaclav Hapla       if (cn > 1) {
31939566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
31949566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3195af9eab45SVaclav Hapla       } else {
3196af9eab45SVaclav Hapla         newarr[co] = arr[i];
3197af9eab45SVaclav Hapla       }
3198af9eab45SVaclav Hapla     }
31999566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3200af9eab45SVaclav Hapla     arr = newarr;
3201af9eab45SVaclav Hapla     n   = newn;
3202af9eab45SVaclav Hapla   }
32039566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3204af9eab45SVaclav Hapla   *depth = depth_;
3205af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3206af9eab45SVaclav Hapla   else {
32079566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
32089566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3209af9eab45SVaclav Hapla   }
3210af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3211af9eab45SVaclav Hapla   else {
32129566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
32139566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3214af9eab45SVaclav Hapla   }
32153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3216af9eab45SVaclav Hapla }
3217af9eab45SVaclav Hapla 
3218af9eab45SVaclav Hapla /*@
3219a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3220af9eab45SVaclav Hapla 
3221a1cb98faSBarry Smith   Not Collective
3222af9eab45SVaclav Hapla 
3223af9eab45SVaclav Hapla   Input Parameters:
3224a1cb98faSBarry Smith + dm     - The `DMPLEX`
3225a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3226af9eab45SVaclav Hapla 
3227d8d19677SJose E. Roman   Output Parameters:
3228a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3229af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3230af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3231af9eab45SVaclav Hapla 
3232af9eab45SVaclav Hapla   Level: advanced
3233af9eab45SVaclav Hapla 
3234a1cb98faSBarry Smith   Note:
3235a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3236af9eab45SVaclav Hapla 
32371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3238a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3239af9eab45SVaclav Hapla @*/
3240d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3241d71ae5a4SJacob Faibussowitsch {
3242af9eab45SVaclav Hapla   PetscInt d, depth_;
3243af9eab45SVaclav Hapla 
3244af9eab45SVaclav Hapla   PetscFunctionBegin;
32459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
32461dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3247af9eab45SVaclav Hapla   if (depth) *depth = 0;
3248af9eab45SVaclav Hapla   if (expandedPoints) {
32499566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
32509566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3251af9eab45SVaclav Hapla   }
3252af9eab45SVaclav Hapla   if (sections) {
32539566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
32549566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3255af9eab45SVaclav Hapla   }
32563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3257d4636a37SVaclav Hapla }
3258d4636a37SVaclav Hapla 
3259552f7358SJed Brown /*@
326092371b87SBarry 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
3261552f7358SJed Brown 
3262a1cb98faSBarry Smith   Not Collective
3263552f7358SJed Brown 
3264552f7358SJed Brown   Input Parameters:
326560225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3266a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
326720f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3268552f7358SJed Brown 
3269552f7358SJed Brown   Level: beginner
3270552f7358SJed Brown 
3271a1cb98faSBarry Smith   Note:
3272a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3273a1cb98faSBarry Smith 
32741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3275552f7358SJed Brown @*/
3276d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3277d71ae5a4SJacob Faibussowitsch {
3278552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3279552f7358SJed Brown   PetscInt dof, off, c;
3280552f7358SJed Brown 
3281552f7358SJed Brown   PetscFunctionBegin;
3282552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
32844f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
32859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3286db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3287db485b19SStefano Zampini     PetscInt pStart, pEnd;
3288db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
328963a3b9bcSJacob 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);
3290552f7358SJed Brown     for (c = 0; c < dof; ++c) {
329163a3b9bcSJacob 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);
3292552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3293552f7358SJed Brown     }
3294db485b19SStefano Zampini   } else {
3295db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3296db485b19SStefano Zampini   }
32973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3298552f7358SJed Brown }
3299552f7358SJed Brown 
3300552f7358SJed Brown /*@C
3301eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3302552f7358SJed Brown 
3303a1cb98faSBarry Smith   Not Collective
3304552f7358SJed Brown 
3305552f7358SJed Brown   Input Parameters:
330660225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3307a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3308552f7358SJed Brown 
3309552f7358SJed Brown   Output Parameter:
331020f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3311b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3312552f7358SJed Brown 
3313552f7358SJed Brown   Level: beginner
3314552f7358SJed Brown 
3315a1cb98faSBarry Smith   Note:
3316b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3317b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3318a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3319b5a892a1SMatthew G. Knepley   with the identity.
3320b5a892a1SMatthew G. Knepley 
332160225df5SJacob Faibussowitsch   Fortran Notes:
3322a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3323a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
33243813dfbdSMatthew G Knepley 
33251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3326552f7358SJed Brown @*/
3327d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3328d71ae5a4SJacob Faibussowitsch {
3329552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3330552f7358SJed Brown   PetscInt off;
3331552f7358SJed Brown 
3332552f7358SJed Brown   PetscFunctionBegin;
3333552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3335552f7358SJed Brown     PetscInt dof;
33369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33374f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3338552f7358SJed Brown   }
33399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
33400d644c17SKarl Rupp 
3341552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
33423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3343552f7358SJed Brown }
3344552f7358SJed Brown 
3345552f7358SJed Brown /*@
3346eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3347552f7358SJed Brown 
3348a1cb98faSBarry Smith   Not Collective
3349552f7358SJed Brown 
3350552f7358SJed Brown   Input Parameters:
335160225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3352a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3353b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3354b5a892a1SMatthew G. Knepley 
3355552f7358SJed Brown   Level: beginner
3356552f7358SJed Brown 
3357a1cb98faSBarry Smith   Notes:
3358a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3359a1cb98faSBarry Smith 
3360a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3361a1cb98faSBarry Smith 
33621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3363552f7358SJed Brown @*/
3364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3365d71ae5a4SJacob Faibussowitsch {
3366552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3367552f7358SJed Brown   PetscInt pStart, pEnd;
3368552f7358SJed Brown   PetscInt dof, off, c;
3369552f7358SJed Brown 
3370552f7358SJed Brown   PetscFunctionBegin;
3371552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33734f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
33749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3375db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3376db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
337763a3b9bcSJacob 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);
3378552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3379552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3380552f7358SJed Brown 
33819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
33821dca8a05SBarry 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);
3383552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3384552f7358SJed Brown     }
3385db485b19SStefano Zampini   } else {
3386db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3387db485b19SStefano Zampini   }
33883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3389552f7358SJed Brown }
3390552f7358SJed Brown 
33917cd05799SMatthew G. Knepley /*@
3392eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
33937cd05799SMatthew G. Knepley 
3394a1cb98faSBarry Smith   Not Collective
33957cd05799SMatthew G. Knepley 
33967cd05799SMatthew G. Knepley   Input Parameters:
339760225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3398a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
33997cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
34007cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
34017cd05799SMatthew G. Knepley 
34027cd05799SMatthew G. Knepley   Level: beginner
34037cd05799SMatthew G. Knepley 
34041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34057cd05799SMatthew G. Knepley @*/
3406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3407d71ae5a4SJacob Faibussowitsch {
3408552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3409552f7358SJed Brown   PetscInt pStart, pEnd;
3410552f7358SJed Brown   PetscInt dof, off;
3411552f7358SJed Brown 
3412552f7358SJed Brown   PetscFunctionBegin;
3413552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3414a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
341663a3b9bcSJacob 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);
341763a3b9bcSJacob 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);
34189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
341963a3b9bcSJacob 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);
3420a03d55ffSStefano Zampini   }
3421a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3422552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
34233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3424552f7358SJed Brown }
3425552f7358SJed Brown 
34267cd05799SMatthew G. Knepley /*@
3427eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
34287cd05799SMatthew G. Knepley 
3429a1cb98faSBarry Smith   Not Collective
34307cd05799SMatthew G. Knepley 
34317cd05799SMatthew G. Knepley   Input Parameters:
343260225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3433a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
34347cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
34357cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
34367cd05799SMatthew G. Knepley 
34377cd05799SMatthew G. Knepley   Level: beginner
34387cd05799SMatthew G. Knepley 
3439a1cb98faSBarry Smith   Note:
3440a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3441b5a892a1SMatthew G. Knepley 
34421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
34437cd05799SMatthew G. Knepley @*/
3444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3445d71ae5a4SJacob Faibussowitsch {
344677c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
344777c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
344877c88f5bSMatthew G Knepley   PetscInt dof, off;
344977c88f5bSMatthew G Knepley 
345077c88f5bSMatthew G Knepley   PetscFunctionBegin;
345177c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3452a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
34539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
345463a3b9bcSJacob 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);
34559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
345663a3b9bcSJacob 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);
3457a03d55ffSStefano Zampini   }
3458a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
345977c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
34603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346177c88f5bSMatthew G Knepley }
346277c88f5bSMatthew G Knepley 
34639f4ada15SMatthew G. Knepley /*@C
34649f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
34659f4ada15SMatthew G. Knepley 
34669f4ada15SMatthew G. Knepley   Not collective
34679f4ada15SMatthew G. Knepley 
34689f4ada15SMatthew G. Knepley   Input Parameters:
34699f4ada15SMatthew G. Knepley + dm - The DMPlex
34709f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
34719f4ada15SMatthew G. Knepley 
34729f4ada15SMatthew G. Knepley   Output Parameters:
347320f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
347420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
34759f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
34769f4ada15SMatthew G. Knepley 
34779f4ada15SMatthew G. Knepley   Level: beginner
34789f4ada15SMatthew G. Knepley 
34799f4ada15SMatthew G. Knepley   Notes:
34809f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
34819f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
348220f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
34839f4ada15SMatthew G. Knepley   with the identity.
34849f4ada15SMatthew G. Knepley 
34859f4ada15SMatthew G. Knepley   Fortran Notes:
348620f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
348720f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
34889f4ada15SMatthew G. Knepley 
34891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
34909f4ada15SMatthew G. Knepley @*/
34919f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
34929f4ada15SMatthew G. Knepley {
34939f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
34949f4ada15SMatthew G. Knepley 
34959f4ada15SMatthew G. Knepley   PetscFunctionBegin;
34969f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34979f4ada15SMatthew G. Knepley   if (mesh->tr) {
34989f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
34999f4ada15SMatthew G. Knepley   } else {
35009f4ada15SMatthew G. Knepley     PetscInt off;
35019f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
35029f4ada15SMatthew G. Knepley       PetscInt dof;
35039f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
35049f4ada15SMatthew G. Knepley       if (dof) {
35054f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
35064f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
35079f4ada15SMatthew G. Knepley       }
35089f4ada15SMatthew G. Knepley     }
35099f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
35108e3a54c0SPierre Jolivet     if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off);
35118e3a54c0SPierre Jolivet     if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off);
35129f4ada15SMatthew G. Knepley   }
35133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35149f4ada15SMatthew G. Knepley }
35159f4ada15SMatthew G. Knepley 
35169f4ada15SMatthew G. Knepley /*@C
35179f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
35189f4ada15SMatthew G. Knepley 
351920f4b53cSBarry Smith   Not Collective
35209f4ada15SMatthew G. Knepley 
35219f4ada15SMatthew G. Knepley   Input Parameters:
35229f4ada15SMatthew G. Knepley + dm   - The DMPlex
352320f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
35249f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
352520f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
35269f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
35279f4ada15SMatthew G. Knepley 
35289f4ada15SMatthew G. Knepley   Level: beginner
35299f4ada15SMatthew G. Knepley 
35309f4ada15SMatthew G. Knepley   Notes:
35319f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
35329f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
353320f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
35349f4ada15SMatthew G. Knepley   with the identity.
35359f4ada15SMatthew G. Knepley 
353660225df5SJacob Faibussowitsch   Fortran Notes:
353720f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
353820f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
35399f4ada15SMatthew G. Knepley 
35401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
35419f4ada15SMatthew G. Knepley @*/
35429f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
35439f4ada15SMatthew G. Knepley {
35449f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
35459f4ada15SMatthew G. Knepley 
35469f4ada15SMatthew G. Knepley   PetscFunctionBegin;
35479f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35489f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
35493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35509f4ada15SMatthew G. Knepley }
35519f4ada15SMatthew G. Knepley 
3552552f7358SJed Brown /*@
3553eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3554552f7358SJed Brown 
3555a1cb98faSBarry Smith   Not Collective
3556552f7358SJed Brown 
3557552f7358SJed Brown   Input Parameters:
355860225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3559a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3560552f7358SJed Brown 
3561552f7358SJed Brown   Output Parameter:
356220f4b53cSBarry Smith . size - The support size for point `p`
3563552f7358SJed Brown 
3564552f7358SJed Brown   Level: beginner
3565552f7358SJed Brown 
35661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3567552f7358SJed Brown @*/
3568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3569d71ae5a4SJacob Faibussowitsch {
3570552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3571552f7358SJed Brown 
3572552f7358SJed Brown   PetscFunctionBegin;
3573552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35744f572ea9SToby Isaac   PetscAssertPointer(size, 3);
35759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
35763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3577552f7358SJed Brown }
3578552f7358SJed Brown 
3579552f7358SJed Brown /*@
3580eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3581552f7358SJed Brown 
3582a1cb98faSBarry Smith   Not Collective
3583552f7358SJed Brown 
3584552f7358SJed Brown   Input Parameters:
358560225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3586a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
358720f4b53cSBarry Smith - size - The support size for point `p`
3588552f7358SJed Brown 
3589a1cb98faSBarry Smith   Level: beginner
3590552f7358SJed Brown 
3591552f7358SJed Brown   Note:
359220f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3593552f7358SJed Brown 
35941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3595552f7358SJed Brown @*/
3596d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3597d71ae5a4SJacob Faibussowitsch {
3598552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3599552f7358SJed Brown 
3600552f7358SJed Brown   PetscFunctionBegin;
3601552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
36033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3604552f7358SJed Brown }
3605552f7358SJed Brown 
3606552f7358SJed Brown /*@C
3607eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3608552f7358SJed Brown 
3609a1cb98faSBarry Smith   Not Collective
3610552f7358SJed Brown 
3611552f7358SJed Brown   Input Parameters:
361260225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3613a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3614552f7358SJed Brown 
3615552f7358SJed Brown   Output Parameter:
361620f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3617552f7358SJed Brown 
3618552f7358SJed Brown   Level: beginner
3619552f7358SJed Brown 
362060225df5SJacob Faibussowitsch   Fortran Notes:
3621a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3622a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
36233813dfbdSMatthew G Knepley 
36241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3625552f7358SJed Brown @*/
3626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3627d71ae5a4SJacob Faibussowitsch {
3628552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3629552f7358SJed Brown   PetscInt off;
3630552f7358SJed Brown 
3631552f7358SJed Brown   PetscFunctionBegin;
3632552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36334f572ea9SToby Isaac   PetscAssertPointer(support, 3);
36349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
36358e3a54c0SPierre Jolivet   *support = PetscSafePointerPlusOffset(mesh->supports, off);
36363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3637552f7358SJed Brown }
3638552f7358SJed Brown 
3639552f7358SJed Brown /*@
364092371b87SBarry 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
3641552f7358SJed Brown 
3642a1cb98faSBarry Smith   Not Collective
3643552f7358SJed Brown 
3644552f7358SJed Brown   Input Parameters:
364560225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3646a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
364720f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3648552f7358SJed Brown 
3649552f7358SJed Brown   Level: beginner
3650552f7358SJed Brown 
3651a1cb98faSBarry Smith   Note:
3652a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3653a1cb98faSBarry Smith 
36541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3655552f7358SJed Brown @*/
3656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3657d71ae5a4SJacob Faibussowitsch {
3658552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3659552f7358SJed Brown   PetscInt pStart, pEnd;
3660552f7358SJed Brown   PetscInt dof, off, c;
3661552f7358SJed Brown 
3662552f7358SJed Brown   PetscFunctionBegin;
3663552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
36659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
36664f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
36679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
366863a3b9bcSJacob 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);
3669552f7358SJed Brown   for (c = 0; c < dof; ++c) {
367063a3b9bcSJacob 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);
3671552f7358SJed Brown     mesh->supports[off + c] = support[c];
3672552f7358SJed Brown   }
36733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3674552f7358SJed Brown }
3675552f7358SJed Brown 
36767cd05799SMatthew G. Knepley /*@
3677eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
36787cd05799SMatthew G. Knepley 
3679a1cb98faSBarry Smith   Not Collective
36807cd05799SMatthew G. Knepley 
36817cd05799SMatthew G. Knepley   Input Parameters:
368260225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3683a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
36847cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
36857cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
36867cd05799SMatthew G. Knepley 
36877cd05799SMatthew G. Knepley   Level: beginner
36887cd05799SMatthew G. Knepley 
36891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
36907cd05799SMatthew G. Knepley @*/
3691d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3692d71ae5a4SJacob Faibussowitsch {
3693552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3694552f7358SJed Brown   PetscInt pStart, pEnd;
3695552f7358SJed Brown   PetscInt dof, off;
3696552f7358SJed Brown 
3697552f7358SJed Brown   PetscFunctionBegin;
3698552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
37009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
37019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
370263a3b9bcSJacob 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);
370363a3b9bcSJacob 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);
370463a3b9bcSJacob 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);
3705552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
37063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3707552f7358SJed Brown }
3708552f7358SJed Brown 
3709b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3710d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3711d71ae5a4SJacob Faibussowitsch {
3712b5a892a1SMatthew G. Knepley   switch (ct) {
3713b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3714b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3715b5a892a1SMatthew G. Knepley     break;
3716b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3717b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3718b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3719b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3720b5a892a1SMatthew G. Knepley     break;
3721b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3722b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3723b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3724b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3725b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3726b5a892a1SMatthew G. Knepley     break;
3727d71ae5a4SJacob Faibussowitsch   default:
3728d71ae5a4SJacob Faibussowitsch     return o;
3729b5a892a1SMatthew G. Knepley   }
3730b5a892a1SMatthew G. Knepley   return o;
3731b5a892a1SMatthew G. Knepley }
3732b5a892a1SMatthew G. Knepley 
3733b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3734d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3735d71ae5a4SJacob Faibussowitsch {
3736b5a892a1SMatthew G. Knepley   switch (ct) {
3737b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3738b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3739b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3740b5a892a1SMatthew G. Knepley     break;
3741b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3742b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3743b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3744b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3745b5a892a1SMatthew G. Knepley     break;
3746b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3747b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3748b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3749b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3750b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3751b5a892a1SMatthew G. Knepley     break;
3752d71ae5a4SJacob Faibussowitsch   default:
3753d71ae5a4SJacob Faibussowitsch     return o;
3754b5a892a1SMatthew G. Knepley   }
3755b5a892a1SMatthew G. Knepley   return o;
3756b5a892a1SMatthew G. Knepley }
3757b5a892a1SMatthew G. Knepley 
3758b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3760d71ae5a4SJacob Faibussowitsch {
3761b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3762b5a892a1SMatthew G. Knepley 
3763b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
37649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3765b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3766b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3767b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3768b5a892a1SMatthew G. Knepley 
37699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
37709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
37719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3772b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3773b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3774b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3775b5a892a1SMatthew G. Knepley 
37769566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3777b5a892a1SMatthew G. Knepley       switch (ct) {
3778b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
37799566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37809566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3781b5a892a1SMatthew G. Knepley         break;
3782b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
37839566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37849566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37859566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3786b5a892a1SMatthew G. Knepley         break;
3787b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
37889566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
37899566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
37909566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
37919566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3792b5a892a1SMatthew G. Knepley         break;
3793d71ae5a4SJacob Faibussowitsch       default:
3794d71ae5a4SJacob Faibussowitsch         break;
3795b5a892a1SMatthew G. Knepley       }
3796b5a892a1SMatthew G. Knepley     }
3797b5a892a1SMatthew G. Knepley   }
37983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3799b5a892a1SMatthew G. Knepley }
3800b5a892a1SMatthew G. Knepley 
380109015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
380209015e70SStefano Zampini {
380309015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
380409015e70SStefano Zampini 
380509015e70SStefano Zampini   PetscFunctionBeginHot;
380609015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
380709015e70SStefano Zampini     if (useCone) {
380809015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
380909015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
381009015e70SStefano Zampini     } else {
381109015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
381209015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
381309015e70SStefano Zampini     }
381409015e70SStefano Zampini   } else {
381509015e70SStefano Zampini     if (useCone) {
381609015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
381709015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
381809015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
381909015e70SStefano Zampini 
382009015e70SStefano Zampini       *size = s->atlasDof[ps];
382109015e70SStefano Zampini       *arr  = mesh->cones + off;
382209015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
382309015e70SStefano Zampini     } else {
382409015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
382509015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
382609015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
382709015e70SStefano Zampini 
382809015e70SStefano Zampini       *size = s->atlasDof[ps];
382909015e70SStefano Zampini       *arr  = mesh->supports + off;
383009015e70SStefano Zampini     }
383109015e70SStefano Zampini   }
383209015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
383309015e70SStefano Zampini }
383409015e70SStefano Zampini 
383509015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
383609015e70SStefano Zampini {
383709015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
383809015e70SStefano Zampini 
383909015e70SStefano Zampini   PetscFunctionBeginHot;
384009015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
384109015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
384209015e70SStefano Zampini   }
384309015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
384409015e70SStefano Zampini }
384509015e70SStefano Zampini 
3846d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3847d71ae5a4SJacob Faibussowitsch {
3848b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3849b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3850b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3851b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3852b5a892a1SMatthew G. Knepley 
3853b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3854b5a892a1SMatthew G. Knepley   if (ornt) {
38559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3856476787b7SMatthew 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;
3857b5a892a1SMatthew G. Knepley   }
3858b5a892a1SMatthew G. Knepley   if (*points) {
3859b5a892a1SMatthew G. Knepley     closure = *points;
3860b5a892a1SMatthew G. Knepley   } else {
3861b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
38629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
38639566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3864b5a892a1SMatthew G. Knepley   }
386509015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3866b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3867b5a892a1SMatthew G. Knepley     closure[off++] = p;
3868b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3869b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3870b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3871b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3872b5a892a1SMatthew G. Knepley     }
3873b5a892a1SMatthew G. Knepley   } else {
387485036b15SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt);
3875b5a892a1SMatthew G. Knepley 
3876b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3877b5a892a1SMatthew G. Knepley     closure[off++] = p;
3878b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3879b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3880b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3881b5a892a1SMatthew G. Knepley 
38829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3883b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3884b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3885b5a892a1SMatthew G. Knepley     }
3886b5a892a1SMatthew G. Knepley   }
388709015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3888b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3889b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3891b5a892a1SMatthew G. Knepley }
3892b5a892a1SMatthew G. Knepley 
3893d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3894d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3895d71ae5a4SJacob Faibussowitsch {
389685036b15SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o);
3897b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3898b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3899b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3900b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3901b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3902b5a892a1SMatthew G. Knepley 
3903b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39049566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
390509015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
39069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3907b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3908b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3909b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39109371c9d4SSatish Balay   if (*points) {
39119371c9d4SSatish Balay     pts = *points;
39129371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3913b5a892a1SMatthew G. Knepley   c        = 0;
3914b5a892a1SMatthew G. Knepley   pts[c++] = point;
3915b5a892a1SMatthew G. Knepley   pts[c++] = o;
39169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
39179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
39189371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39199371c9d4SSatish Balay     pts[c++] = closure[cl];
39209371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39219371c9d4SSatish Balay   }
39229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
39239371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
39249371c9d4SSatish Balay     pts[c++] = closure[cl];
39259371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
39269371c9d4SSatish Balay   }
39279566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3928b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
39299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3930b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3931b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3932b5a892a1SMatthew G. Knepley   }
393309015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3934b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3935b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3936b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3937b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3938b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3939b5a892a1SMatthew G. Knepley 
39409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
394185036b15SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
394209015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3943b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3944b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3945b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3946b5a892a1SMatthew G. Knepley 
39479371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
39489371c9d4SSatish Balay           if (pts[i] == cp) break;
3949b5a892a1SMatthew G. Knepley         if (i == c) {
39509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3951b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3952b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3953b5a892a1SMatthew G. Knepley         }
3954b5a892a1SMatthew G. Knepley       }
395509015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3956b5a892a1SMatthew G. Knepley     }
3957b5a892a1SMatthew G. Knepley   }
3958b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3959b5a892a1SMatthew G. Knepley   *points    = pts;
39603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3961b5a892a1SMatthew G. Knepley }
3962b5a892a1SMatthew G. Knepley 
3963d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3964d71ae5a4SJacob Faibussowitsch {
3965b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3966b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3967b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3968b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3969b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3970b5a892a1SMatthew G. Knepley 
3971b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
39729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3973b5a892a1SMatthew G. Knepley   if (depth == 1) {
39749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
39753ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3976b5a892a1SMatthew G. Knepley   }
39779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3978476787b7SMatthew 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;
3979c306944fSJed Brown   if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) {
39809566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
39813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3982b5a892a1SMatthew G. Knepley   }
39839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3984b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3985b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3986b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
39879566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
39889371c9d4SSatish Balay   if (*points) {
39899371c9d4SSatish Balay     closure = *points;
39909371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3991b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3992b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3993b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3994b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3995b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3996b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3997b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3998b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3999b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
4000b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
400185036b15SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangement(qt, o);
400209015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
4003b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
4004b5a892a1SMatthew G. Knepley 
4005b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
400685036b15SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2;
400763a3b9bcSJacob 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);
4008b5a892a1SMatthew G. Knepley     }
400909015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4010b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
4011b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
4012b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
4013b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
40149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
4015b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
4016b5a892a1SMatthew G. Knepley       PetscInt       c;
4017b5a892a1SMatthew G. Knepley 
4018b5a892a1SMatthew G. Knepley       /* Check for duplicate */
4019b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
4020b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
4021b5a892a1SMatthew G. Knepley       }
4022b5a892a1SMatthew G. Knepley       if (c == closureSize) {
4023b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
4024b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
4025b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
4026b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
4027b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
4028b5a892a1SMatthew G. Knepley       }
4029b5a892a1SMatthew G. Knepley     }
403009015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
4031b5a892a1SMatthew G. Knepley   }
40329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
4033b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
4034b5a892a1SMatthew G. Knepley   if (points) *points = closure;
40353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4036b5a892a1SMatthew G. Knepley }
4037b5a892a1SMatthew G. Knepley 
4038552f7358SJed Brown /*@C
4039eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
4040552f7358SJed Brown 
4041a1cb98faSBarry Smith   Not Collective
4042552f7358SJed Brown 
4043552f7358SJed Brown   Input Parameters:
4044a1cb98faSBarry Smith + dm      - The `DMPLEX`
4045b5a892a1SMatthew G. Knepley . p       - The mesh point
4046a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
4047552f7358SJed Brown 
40486b867d5aSJose E. Roman   Input/Output Parameter:
40496b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
405020f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
40516b867d5aSJose E. Roman 
40526b867d5aSJose E. Roman   Output Parameter:
405320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4054552f7358SJed Brown 
4055a1cb98faSBarry Smith   Level: beginner
4056a1cb98faSBarry Smith 
4057552f7358SJed Brown   Note:
405820f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
4059552f7358SJed Brown 
406060225df5SJacob Faibussowitsch   Fortran Notes:
406120f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
40623813dfbdSMatthew G Knepley 
40631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4064552f7358SJed Brown @*/
4065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4066d71ae5a4SJacob Faibussowitsch {
4067b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4068552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40694f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
40704f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
40719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
40723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40739bf0dad6SMatthew G. Knepley }
40749bf0dad6SMatthew G. Knepley 
4075552f7358SJed Brown /*@C
4076eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
4077552f7358SJed Brown 
4078a1cb98faSBarry Smith   Not Collective
4079552f7358SJed Brown 
4080552f7358SJed Brown   Input Parameters:
4081a1cb98faSBarry Smith + dm        - The `DMPLEX`
4082b5a892a1SMatthew G. Knepley . p         - The mesh point
4083a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
408420f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
4085b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
4086552f7358SJed Brown 
4087a1cb98faSBarry Smith   Level: beginner
4088a1cb98faSBarry Smith 
4089552f7358SJed Brown   Note:
409020f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
4091552f7358SJed Brown 
40921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
4093552f7358SJed Brown @*/
4094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
4095d71ae5a4SJacob Faibussowitsch {
4096b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
4097552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
40984ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
40999566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
41003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4101552f7358SJed Brown }
4102552f7358SJed Brown 
4103552f7358SJed Brown /*@
4104eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
4105552f7358SJed Brown 
4106a1cb98faSBarry Smith   Not Collective
4107552f7358SJed Brown 
4108552f7358SJed Brown   Input Parameter:
410960225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4110552f7358SJed Brown 
4111552f7358SJed Brown   Output Parameters:
4112552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
4113552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
4114552f7358SJed Brown 
4115552f7358SJed Brown   Level: beginner
4116552f7358SJed Brown 
41171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
4118552f7358SJed Brown @*/
4119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
4120d71ae5a4SJacob Faibussowitsch {
4121552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
4122552f7358SJed Brown 
4123552f7358SJed Brown   PetscFunctionBegin;
4124552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41251baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
41261baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
41273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4128552f7358SJed Brown }
4129552f7358SJed Brown 
4130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
4131d71ae5a4SJacob Faibussowitsch {
4132552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
41336302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
4134552f7358SJed Brown 
4135552f7358SJed Brown   PetscFunctionBegin;
4136552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
41389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
41399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
41409566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
41416302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41426302a7fbSVaclav Hapla   if (maxSupportSize) {
41439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
41449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
41459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
4146552f7358SJed Brown   }
41473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4148552f7358SJed Brown }
4149552f7358SJed Brown 
4150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
4151d71ae5a4SJacob Faibussowitsch {
4152552f7358SJed Brown   PetscFunctionBegin;
41539566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
4154dd072f5fSMatthew G. Knepley   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm));
4155ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
4156736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
415795602cf2SAlexis Marboeuf     PetscSF sfNatural;
4158f94b4a02SBlaise Bourdin 
41593dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
41609566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
416195602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
4162c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
4163f94b4a02SBlaise Bourdin   }
41643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4165552f7358SJed Brown }
4166552f7358SJed Brown 
4167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
4168d71ae5a4SJacob Faibussowitsch {
41693dcd263cSBlaise Bourdin   PetscInt i = 0;
41702adcc780SMatthew G. Knepley 
41712adcc780SMatthew G. Knepley   PetscFunctionBegin;
41729566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
41739566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
4174c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
41753dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
41763dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
417795602cf2SAlexis Marboeuf       PetscSF sfNatural;
41783dcd263cSBlaise Bourdin 
41793dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
41809566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
4181c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
418295602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4183c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
41843dcd263cSBlaise Bourdin       break;
41853dcd263cSBlaise Bourdin     }
41863dcd263cSBlaise Bourdin   }
41873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
41882adcc780SMatthew G. Knepley }
41892adcc780SMatthew G. Knepley 
4190552f7358SJed Brown /*@
4191eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4192552f7358SJed Brown 
4193a1cb98faSBarry Smith   Not Collective
4194552f7358SJed Brown 
4195552f7358SJed Brown   Input Parameter:
419660225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4197552f7358SJed Brown 
4198552f7358SJed Brown   Level: beginner
4199552f7358SJed Brown 
4200a1cb98faSBarry Smith   Note:
4201a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4202a1cb98faSBarry Smith 
42031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4204552f7358SJed Brown @*/
4205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4206d71ae5a4SJacob Faibussowitsch {
4207552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4208552f7358SJed Brown   PetscInt *offsets;
4209552f7358SJed Brown   PetscInt  supportSize;
4210552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4211552f7358SJed Brown 
4212552f7358SJed Brown   PetscFunctionBegin;
4213552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
421428b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
42159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4216552f7358SJed Brown   /* Calculate support sizes */
42179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4218552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4219552f7358SJed Brown     PetscInt dof, off, c;
4220552f7358SJed Brown 
42219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
422348a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4224552f7358SJed Brown   }
42259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4226552f7358SJed Brown   /* Calculate supports */
42279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
42289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
42299566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4230552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4231552f7358SJed Brown     PetscInt dof, off, c;
4232552f7358SJed Brown 
42339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
42349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4235552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4236552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4237552f7358SJed Brown       PetscInt       offS;
4238552f7358SJed Brown 
42399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
42400d644c17SKarl Rupp 
4241552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4242552f7358SJed Brown       ++offsets[q];
4243552f7358SJed Brown     }
4244552f7358SJed Brown   }
42459566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
42469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
42473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4248552f7358SJed Brown }
4249552f7358SJed Brown 
4250d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4251d71ae5a4SJacob Faibussowitsch {
4252277ea44aSLisandro Dalcin   IS stratumIS;
4253277ea44aSLisandro Dalcin 
4254277ea44aSLisandro Dalcin   PetscFunctionBegin;
42553ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
425676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4257277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4258277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
42599566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4260277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
42619566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
42629371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
42639371c9d4SSatish Balay         overlap = PETSC_TRUE;
42649371c9d4SSatish Balay         break;
42659371c9d4SSatish Balay       }
4266277ea44aSLisandro Dalcin     }
426763a3b9bcSJacob 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);
4268277ea44aSLisandro Dalcin   }
42699566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
42709566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
42719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
42723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4273277ea44aSLisandro Dalcin }
4274277ea44aSLisandro Dalcin 
4275e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label)
4276e91fa0a1SMatthew G. Knepley {
4277e91fa0a1SMatthew G. Knepley   PetscInt *pMin, *pMax;
4278e91fa0a1SMatthew G. Knepley   PetscInt  pStart, pEnd;
4279e91fa0a1SMatthew G. Knepley   PetscInt  dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT;
4280e91fa0a1SMatthew G. Knepley 
4281e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4282e91fa0a1SMatthew G. Knepley   {
4283e91fa0a1SMatthew G. Knepley     DMLabel label2;
4284e91fa0a1SMatthew G. Knepley 
4285e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellTypeLabel(dm, &label2));
4286e91fa0a1SMatthew G. Knepley     PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view"));
4287e91fa0a1SMatthew G. Knepley   }
4288e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4289e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4290e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4291e91fa0a1SMatthew G. Knepley 
4292e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4293e91fa0a1SMatthew G. Knepley     dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin);
4294e91fa0a1SMatthew G. Knepley     dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax);
4295e91fa0a1SMatthew G. Knepley   }
4296e91fa0a1SMatthew G. Knepley   PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax));
4297e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4298e91fa0a1SMatthew G. Knepley     pMin[d] = PETSC_MAX_INT;
4299e91fa0a1SMatthew G. Knepley     pMax[d] = PETSC_MIN_INT;
4300e91fa0a1SMatthew G. Knepley   }
4301e91fa0a1SMatthew G. Knepley   for (PetscInt p = pStart; p < pEnd; ++p) {
4302e91fa0a1SMatthew G. Knepley     DMPolytopeType ct;
4303e91fa0a1SMatthew G. Knepley     PetscInt       d;
4304e91fa0a1SMatthew G. Knepley 
4305e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexGetCellType(dm, p, &ct));
4306e91fa0a1SMatthew G. Knepley     d       = DMPolytopeTypeGetDim(ct);
4307e91fa0a1SMatthew G. Knepley     pMin[d] = PetscMin(p, pMin[d]);
4308e91fa0a1SMatthew G. Knepley     pMax[d] = PetscMax(p, pMax[d]);
4309e91fa0a1SMatthew G. Knepley   }
4310e91fa0a1SMatthew G. Knepley   for (PetscInt d = dmin; d <= dmax; ++d) {
4311e91fa0a1SMatthew G. Knepley     if (pMin[d] > pMax[d]) continue;
4312e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1));
4313e91fa0a1SMatthew G. Knepley   }
4314e91fa0a1SMatthew G. Knepley   PetscCall(PetscFree2(pMin, pMax));
4315e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4316e91fa0a1SMatthew G. Knepley }
4317e91fa0a1SMatthew G. Knepley 
4318e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label)
4319e91fa0a1SMatthew G. Knepley {
4320e91fa0a1SMatthew G. Knepley   PetscInt pStart, pEnd;
4321e91fa0a1SMatthew G. Knepley   PetscInt numRoots = 0, numLeaves = 0;
4322e91fa0a1SMatthew G. Knepley 
4323e91fa0a1SMatthew G. Knepley   PetscFunctionBegin;
4324e91fa0a1SMatthew G. Knepley   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4325e91fa0a1SMatthew G. Knepley   {
4326e91fa0a1SMatthew G. Knepley     /* Initialize roots and count leaves */
4327e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4328e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4329e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4330e91fa0a1SMatthew G. Knepley 
4331e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4332e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4333e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4334e91fa0a1SMatthew G. Knepley       if (!coneSize && supportSize) {
4335e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4336e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4337e91fa0a1SMatthew G. Knepley         ++numRoots;
4338e91fa0a1SMatthew G. Knepley       } else if (!supportSize && coneSize) {
4339e91fa0a1SMatthew G. Knepley         ++numLeaves;
4340e91fa0a1SMatthew G. Knepley       } else if (!supportSize && !coneSize) {
4341e91fa0a1SMatthew G. Knepley         /* Isolated points */
4342e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4343e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4344e91fa0a1SMatthew G. Knepley       }
4345e91fa0a1SMatthew G. Knepley     }
4346e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4347e91fa0a1SMatthew G. Knepley   }
4348e91fa0a1SMatthew G. Knepley 
4349e91fa0a1SMatthew G. Knepley   if (numRoots + numLeaves == (pEnd - pStart)) {
4350e91fa0a1SMatthew G. Knepley     PetscInt sMin = PETSC_MAX_INT;
4351e91fa0a1SMatthew G. Knepley     PetscInt sMax = PETSC_MIN_INT;
4352e91fa0a1SMatthew G. Knepley     PetscInt coneSize, supportSize;
4353e91fa0a1SMatthew G. Knepley 
4354e91fa0a1SMatthew G. Knepley     for (PetscInt p = pStart; p < pEnd; ++p) {
4355e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4356e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4357e91fa0a1SMatthew G. Knepley       if (!supportSize && coneSize) {
4358e91fa0a1SMatthew G. Knepley         sMin = PetscMin(p, sMin);
4359e91fa0a1SMatthew G. Knepley         sMax = PetscMax(p, sMax);
4360e91fa0a1SMatthew G. Knepley       }
4361e91fa0a1SMatthew G. Knepley     }
4362e91fa0a1SMatthew G. Knepley     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4363e91fa0a1SMatthew G. Knepley   } else {
4364e91fa0a1SMatthew G. Knepley     PetscInt level = 0;
4365e91fa0a1SMatthew G. Knepley     PetscInt qStart, qEnd;
4366e91fa0a1SMatthew G. Knepley 
4367e91fa0a1SMatthew G. Knepley     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4368e91fa0a1SMatthew G. Knepley     while (qEnd > qStart) {
4369e91fa0a1SMatthew G. Knepley       PetscInt sMin = PETSC_MAX_INT;
4370e91fa0a1SMatthew G. Knepley       PetscInt sMax = PETSC_MIN_INT;
4371e91fa0a1SMatthew G. Knepley 
4372e91fa0a1SMatthew G. Knepley       for (PetscInt q = qStart; q < qEnd; ++q) {
4373e91fa0a1SMatthew G. Knepley         const PetscInt *support;
4374e91fa0a1SMatthew G. Knepley         PetscInt        supportSize;
4375e91fa0a1SMatthew G. Knepley 
4376e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
4377e91fa0a1SMatthew G. Knepley         PetscCall(DMPlexGetSupport(dm, q, &support));
4378e91fa0a1SMatthew G. Knepley         for (PetscInt s = 0; s < supportSize; ++s) {
4379e91fa0a1SMatthew G. Knepley           sMin = PetscMin(support[s], sMin);
4380e91fa0a1SMatthew G. Knepley           sMax = PetscMax(support[s], sMax);
4381e91fa0a1SMatthew G. Knepley         }
4382e91fa0a1SMatthew G. Knepley       }
4383e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetNumValues(label, &level));
4384e91fa0a1SMatthew G. Knepley       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
4385e91fa0a1SMatthew G. Knepley       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4386e91fa0a1SMatthew G. Knepley     }
4387e91fa0a1SMatthew G. Knepley   }
4388e91fa0a1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
4389e91fa0a1SMatthew G. Knepley }
4390e91fa0a1SMatthew G. Knepley 
4391552f7358SJed Brown /*@
4392a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4393552f7358SJed Brown 
439420f4b53cSBarry Smith   Collective
4395552f7358SJed Brown 
4396552f7358SJed Brown   Input Parameter:
439760225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4398552f7358SJed Brown 
4399a1cb98faSBarry Smith   Level: beginner
4400552f7358SJed Brown 
4401552f7358SJed Brown   Notes:
4402a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4403a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4404a4e35b19SJacob Faibussowitsch 
4405a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4406a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4407a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4408b1bb481bSMatthew 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
4409a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4410a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4411a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4412552f7358SJed Brown 
4413b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4414b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4415b1bb481bSMatthew 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
4416b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4417a1cb98faSBarry Smith .vb
4418a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4419a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4420a1cb98faSBarry Smith .ve
4421a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4422a1cb98faSBarry Smith .vb
4423a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4424a1cb98faSBarry Smith    depth 1 = {e0, c0}
4425a1cb98faSBarry Smith .ve
4426b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4427b1bb481bSMatthew Knepley 
4428a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4429552f7358SJed Brown 
44301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4431552f7358SJed Brown @*/
4432d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4433d71ae5a4SJacob Faibussowitsch {
4434df0420ecSMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
4435aa50250dSMatthew G. Knepley   DMLabel   label;
4436e91fa0a1SMatthew G. Knepley   PetscBool flg = PETSC_FALSE;
4437552f7358SJed Brown 
4438552f7358SJed Brown   PetscFunctionBegin;
4439552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4441277ea44aSLisandro Dalcin 
4442e91fa0a1SMatthew G. Knepley   // Create depth label
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 {
5527*c789d87fSToby Isaac   PetscSection section;
55283e922f36SToby Isaac   PetscInt     maxHeight;
5529dd4c3f67SMatthew G. Knepley   const char  *prefix;
5530552f7358SJed Brown 
5531552f7358SJed Brown   PetscFunctionBegin;
55329566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5533dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5534dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5535dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
55369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
55379566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
55389566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
55399566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
55409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
55418f4c458bSMatthew G. Knepley 
55429566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
55439566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5544dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5545dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
55463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5547552f7358SJed Brown }
5548552f7358SJed Brown 
5549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5550d71ae5a4SJacob Faibussowitsch {
55516858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
55526858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5553f19dbd58SToby Isaac 
5554f19dbd58SToby Isaac   PetscFunctionBegin;
5555f19dbd58SToby Isaac   *field = NULL;
55569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
55579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
55586858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
55596858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5560f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
55616858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
55626858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5563f19dbd58SToby Isaac   }
55643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5565f19dbd58SToby Isaac }
5566f19dbd58SToby Isaac 
55677cd05799SMatthew G. Knepley /*@C
55687cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
55697cd05799SMatthew G. Knepley 
55707cd05799SMatthew G. Knepley   Not Collective
55717cd05799SMatthew G. Knepley 
55722fe279fdSBarry Smith   Input Parameter:
5573a1cb98faSBarry Smith . dm - The `DMPLEX` object
55747cd05799SMatthew G. Knepley 
55757cd05799SMatthew G. Knepley   Output Parameter:
5576a1cb98faSBarry Smith . section - The `PetscSection` object
55777cd05799SMatthew G. Knepley 
55787cd05799SMatthew G. Knepley   Level: developer
55797cd05799SMatthew G. Knepley 
55801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
55817cd05799SMatthew G. Knepley @*/
5582d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5583d71ae5a4SJacob Faibussowitsch {
5584552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5585552f7358SJed Brown 
5586552f7358SJed Brown   PetscFunctionBegin;
5587552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5588552f7358SJed Brown   if (section) *section = mesh->coneSection;
55893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5590552f7358SJed Brown }
5591552f7358SJed Brown 
55927cd05799SMatthew G. Knepley /*@C
55937cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
55947cd05799SMatthew G. Knepley 
55957cd05799SMatthew G. Knepley   Not Collective
55967cd05799SMatthew G. Knepley 
55972fe279fdSBarry Smith   Input Parameter:
5598a1cb98faSBarry Smith . dm - The `DMPLEX` object
55997cd05799SMatthew G. Knepley 
56007cd05799SMatthew G. Knepley   Output Parameter:
5601a1cb98faSBarry Smith . section - The `PetscSection` object
56027cd05799SMatthew G. Knepley 
56037cd05799SMatthew G. Knepley   Level: developer
56047cd05799SMatthew G. Knepley 
56051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
56067cd05799SMatthew G. Knepley @*/
5607d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5608d71ae5a4SJacob Faibussowitsch {
56098cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
56108cb4d582SMatthew G. Knepley 
56118cb4d582SMatthew G. Knepley   PetscFunctionBegin;
56128cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56138cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
56143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56158cb4d582SMatthew G. Knepley }
56168cb4d582SMatthew G. Knepley 
56177cd05799SMatthew G. Knepley /*@C
56187cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
56197cd05799SMatthew G. Knepley 
56207cd05799SMatthew G. Knepley   Not Collective
56217cd05799SMatthew G. Knepley 
56222fe279fdSBarry Smith   Input Parameter:
5623a1cb98faSBarry Smith . dm - The `DMPLEX` object
56247cd05799SMatthew G. Knepley 
56257cd05799SMatthew G. Knepley   Output Parameter:
56267cd05799SMatthew G. Knepley . cones - The cone for each point
56277cd05799SMatthew G. Knepley 
56287cd05799SMatthew G. Knepley   Level: developer
56297cd05799SMatthew G. Knepley 
56301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
56317cd05799SMatthew G. Knepley @*/
5632d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5633d71ae5a4SJacob Faibussowitsch {
5634552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5635552f7358SJed Brown 
5636552f7358SJed Brown   PetscFunctionBegin;
5637552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5638552f7358SJed Brown   if (cones) *cones = mesh->cones;
56393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5640552f7358SJed Brown }
5641552f7358SJed Brown 
56427cd05799SMatthew G. Knepley /*@C
56437cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
56447cd05799SMatthew G. Knepley 
56457cd05799SMatthew G. Knepley   Not Collective
56467cd05799SMatthew G. Knepley 
56472fe279fdSBarry Smith   Input Parameter:
5648a1cb98faSBarry Smith . dm - The `DMPLEX` object
56497cd05799SMatthew G. Knepley 
56507cd05799SMatthew G. Knepley   Output Parameter:
5651b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
56527cd05799SMatthew G. Knepley 
56537cd05799SMatthew G. Knepley   Level: developer
56547cd05799SMatthew G. Knepley 
5655b5a892a1SMatthew G. Knepley   Notes:
5656a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5657b5a892a1SMatthew G. Knepley 
5658a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5659b5a892a1SMatthew G. Knepley 
56601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
56617cd05799SMatthew G. Knepley @*/
5662d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5663d71ae5a4SJacob Faibussowitsch {
5664552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5665552f7358SJed Brown 
5666552f7358SJed Brown   PetscFunctionBegin;
5667552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5668552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
56693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5670552f7358SJed Brown }
5671552f7358SJed Brown 
5672552f7358SJed Brown /******************************** FEM Support **********************************/
5673552f7358SJed Brown 
5674d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS)
5675d2b2dc1eSMatthew G. Knepley {
5676d2b2dc1eSMatthew G. Knepley   PetscInt depth;
5677d2b2dc1eSMatthew G. Knepley 
5678d2b2dc1eSMatthew G. Knepley   PetscFunctionBegin;
5679d2b2dc1eSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
5680d2b2dc1eSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS));
5681d2b2dc1eSMatthew G. Knepley   if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS));
5682d2b2dc1eSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5683d2b2dc1eSMatthew G. Knepley }
5684d2b2dc1eSMatthew G. Knepley 
56855962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS)
56865962854dSMatthew G. Knepley {
56875962854dSMatthew G. Knepley   PetscInt depth;
56885962854dSMatthew G. Knepley 
56895962854dSMatthew G. Knepley   PetscFunctionBegin;
56905962854dSMatthew G. Knepley   PetscCall(DMPlexGetDepth(plex, &depth));
56915962854dSMatthew G. Knepley   PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS));
56925962854dSMatthew G. Knepley   if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS));
56935962854dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
56945962854dSMatthew G. Knepley }
56955962854dSMatthew G. Knepley 
56969e8305c2SJed Brown /*
56979e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
56989e8305c2SJed Brown  representing a line in the section.
56999e8305c2SJed Brown */
57005f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor)
5701d71ae5a4SJacob Faibussowitsch {
5702e327e467SRezgar Shakeri   PetscObject  obj;
5703e327e467SRezgar Shakeri   PetscClassId id;
5704e327e467SRezgar Shakeri   PetscFE      fe = NULL;
5705e327e467SRezgar Shakeri 
57069e8305c2SJed Brown   PetscFunctionBeginHot;
57079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5708e327e467SRezgar Shakeri   PetscCall(DMGetField(dm, field, NULL, &obj));
5709e327e467SRezgar Shakeri   PetscCall(PetscObjectGetClassId(obj, &id));
5710e327e467SRezgar Shakeri   if (id == PETSCFE_CLASSID) fe = (PetscFE)obj;
5711e327e467SRezgar Shakeri 
5712e327e467SRezgar Shakeri   if (!fe) {
5713e327e467SRezgar Shakeri     /* Assume the full interpolated mesh is in the chart; lines in particular */
57149e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
57159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
57169e8305c2SJed Brown     *k = *k / *Nc + 1;
5717e327e467SRezgar Shakeri   } else {
5718e327e467SRezgar Shakeri     PetscInt       dual_space_size, dim;
57195f82726aSMatthew G. Knepley     PetscDualSpace dsp;
57205f82726aSMatthew G. Knepley 
5721e327e467SRezgar Shakeri     PetscCall(DMGetDimension(dm, &dim));
57225f82726aSMatthew G. Knepley     PetscCall(PetscFEGetDualSpace(fe, &dsp));
57235f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size));
5724e327e467SRezgar Shakeri     *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1;
57255f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous));
57265f82726aSMatthew G. Knepley     PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor));
57275f82726aSMatthew G. Knepley   }
57285f82726aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
57295f82726aSMatthew G. Knepley }
57305f82726aSMatthew G. Knepley 
57315f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof)
57325f82726aSMatthew G. Knepley {
57335f82726aSMatthew G. Knepley   PetscFunctionBeginHot;
57345f82726aSMatthew G. Knepley   if (tensor) {
57355f82726aSMatthew G. Knepley     *dof = PetscPowInt(k + 1, dim);
57365f82726aSMatthew G. Knepley   } else {
57375f82726aSMatthew G. Knepley     switch (dim) {
57385f82726aSMatthew G. Knepley     case 1:
57395f82726aSMatthew G. Knepley       *dof = k + 1;
57405f82726aSMatthew G. Knepley       break;
57415f82726aSMatthew G. Knepley     case 2:
57425f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2)) / 2;
57435f82726aSMatthew G. Knepley       break;
57445f82726aSMatthew G. Knepley     case 3:
57455f82726aSMatthew G. Knepley       *dof = ((k + 1) * (k + 2) * (k + 3)) / 6;
57465f82726aSMatthew G. Knepley       break;
57475f82726aSMatthew G. Knepley     default:
57485f82726aSMatthew G. Knepley       *dof = 0;
57495f82726aSMatthew G. Knepley     }
57509e8305c2SJed Brown   }
57513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57529e8305c2SJed Brown }
57539e8305c2SJed Brown 
5754a4355906SMatthew Knepley /*@
5755bc1eb3faSJed Brown 
5756bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5757bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
575820f4b53cSBarry Smith   section provided (or the section of the `DM`).
5759a4355906SMatthew Knepley 
5760a4355906SMatthew Knepley   Input Parameters:
576120f4b53cSBarry Smith + dm      - The `DM`
576220f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
576320f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5764a4355906SMatthew Knepley 
5765bc1eb3faSJed Brown   Example:
5766bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5767bc1eb3faSJed Brown .vb
5768bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5769bc1eb3faSJed Brown 
5770bc1eb3faSJed Brown   v4 -- e6 -- v3
5771bc1eb3faSJed Brown   |           |
5772bc1eb3faSJed Brown   e7    c0    e8
5773bc1eb3faSJed Brown   |           |
5774bc1eb3faSJed Brown   v1 -- e5 -- v2
5775bc1eb3faSJed Brown .ve
5776bc1eb3faSJed Brown 
5777bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5778bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5779bc1eb3faSJed Brown .vb
5780bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5781bc1eb3faSJed Brown     v1 -> [4]
5782bc1eb3faSJed Brown     ...
5783bc1eb3faSJed Brown     e5 -> [8, 9]
5784bc1eb3faSJed Brown .ve
5785bc1eb3faSJed Brown 
5786bc1eb3faSJed Brown   which corresponds to the dofs
5787bc1eb3faSJed Brown .vb
5788bc1eb3faSJed Brown     6   10  11  7
5789bc1eb3faSJed Brown     13  2   3   15
5790bc1eb3faSJed Brown     12  0   1   14
5791bc1eb3faSJed Brown     4   8   9   5
5792bc1eb3faSJed Brown .ve
5793bc1eb3faSJed Brown 
5794bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5795bc1eb3faSJed Brown .vb
5796bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5797bc1eb3faSJed Brown .ve
5798bc1eb3faSJed Brown 
5799bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5800bc1eb3faSJed Brown .vb
5801bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5802bc1eb3faSJed Brown .ve
5803bc1eb3faSJed Brown 
5804a4355906SMatthew Knepley   Level: developer
5805a4355906SMatthew Knepley 
5806da9ac489SAlbert Cowie   Notes:
5807a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5808a1cb98faSBarry Smith   degree of the basis.
5809a1cb98faSBarry Smith 
5810da9ac489SAlbert Cowie   This is required to run with libCEED.
5811da9ac489SAlbert Cowie 
58121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5813a4355906SMatthew Knepley @*/
5814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5815d71ae5a4SJacob Faibussowitsch {
58167391a63aSMatthew G. Knepley   DMLabel   label;
5817bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
58185f82726aSMatthew G. Knepley   PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE;
58193194fc30SMatthew G. Knepley 
58203194fc30SMatthew G. Knepley   PetscFunctionBegin;
58219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
58223ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5823a433471fSStefano Zampini   if (point < 0) {
5824a433471fSStefano Zampini     PetscInt sStart, sEnd;
5825a433471fSStefano Zampini 
58269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5827a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5828a433471fSStefano Zampini   }
58299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
58309566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
58319566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58329371c9d4SSatish Balay   if (depth == 1) {
58339371c9d4SSatish Balay     eStart = point;
58349371c9d4SSatish Balay   } else if (depth == dim) {
58357391a63aSMatthew G. Knepley     const PetscInt *cone;
58367391a63aSMatthew G. Knepley 
58379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5838d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5839d4e6627bSStefano Zampini     else if (dim == 3) {
5840d4e6627bSStefano Zampini       const PetscInt *cone2;
58419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5842d4e6627bSStefano Zampini       eStart = cone2[0];
584363a3b9bcSJacob 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);
584463a3b9bcSJacob 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);
5845e327e467SRezgar Shakeri 
58469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5847bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5848bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5849bb197d40SJed Brown     PetscInt *perm;
5850bb197d40SJed Brown 
58513194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
58525f82726aSMatthew G. Knepley       PetscInt dof;
58535f82726aSMatthew G. Knepley 
58545f82726aSMatthew G. Knepley       PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58555f82726aSMatthew 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);
58565f82726aSMatthew G. Knepley       if (!continuous && d < dim) continue;
58575f82726aSMatthew G. Knepley       PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58585f82726aSMatthew G. Knepley       size += dof * Nc;
58593194fc30SMatthew G. Knepley     }
58609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
58613194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5862bb197d40SJed Brown       switch (d) {
5863babf31e0SJed Brown       case 1:
58645f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58655f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
5866babf31e0SJed Brown         /*
5867babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5868babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5869babf31e0SJed Brown          */
5870e327e467SRezgar Shakeri         if (continuous) {
5871babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
58729371c9d4SSatish Balay           for (i = 0; i < k - 1; i++)
58739371c9d4SSatish Balay             for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5874babf31e0SJed Brown           for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5875babf31e0SJed Brown           foffset = offset;
5876e327e467SRezgar Shakeri         } else {
58775f82726aSMatthew G. Knepley           PetscInt dof;
58785f82726aSMatthew G. Knepley 
58795f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
58805f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
58815f82726aSMatthew G. Knepley           foffset = offset;
5882e327e467SRezgar Shakeri         }
5883babf31e0SJed Brown         break;
588489eabcffSMatthew G. Knepley       case 2:
58853194fc30SMatthew 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} */
58865f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
58875f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
58883194fc30SMatthew G. Knepley         /* The SEM order is
58893194fc30SMatthew G. Knepley 
58903194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
589189eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
58923194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
58933194fc30SMatthew G. Knepley          */
5894e327e467SRezgar Shakeri         if (continuous) {
58953194fc30SMatthew G. Knepley           const PetscInt of   = 0;
58963194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
58973194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
58983194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
58993194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
59003194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
59013194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
59023194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
59033194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
59043194fc30SMatthew G. Knepley           PetscInt       o;
59053194fc30SMatthew G. Knepley 
59063194fc30SMatthew G. Knepley           /* bottom */
59073194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
59089371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
59099371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
59103194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
59113194fc30SMatthew G. Knepley           /* middle */
59123194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
59133194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
59149371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++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] = (oer + i) * Nc + c + foffset;
59173194fc30SMatthew G. Knepley           }
59183194fc30SMatthew G. Knepley           /* top */
59193194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
59209371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --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] = ovrt * Nc + c + foffset;
59233194fc30SMatthew G. Knepley           foffset = offset;
5924e327e467SRezgar Shakeri         } else {
59255f82726aSMatthew G. Knepley           PetscInt dof;
59265f82726aSMatthew G. Knepley 
59275f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
59285f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
59295f82726aSMatthew G. Knepley           foffset = offset;
59303194fc30SMatthew G. Knepley         }
593189eabcffSMatthew G. Knepley         break;
593289eabcffSMatthew G. Knepley       case 3:
593389eabcffSMatthew G. Knepley         /* The original hex closure is
593489eabcffSMatthew G. Knepley 
593589eabcffSMatthew G. Knepley          {c,
593689eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
593789eabcffSMatthew 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,
593889eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
593989eabcffSMatthew G. Knepley          */
59405f82726aSMatthew G. Knepley         PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor));
59415f82726aSMatthew G. Knepley         if (!continuous && d < dim) continue;
594289eabcffSMatthew G. Knepley         /* The SEM order is
594389eabcffSMatthew G. Knepley          Bottom Slice
594489eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
594589eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
594689eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
594789eabcffSMatthew G. Knepley 
594889eabcffSMatthew G. Knepley          Middle Slice (j)
594989eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
595089eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
595189eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
595289eabcffSMatthew G. Knepley 
595389eabcffSMatthew G. Knepley          Top Slice
595489eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
595589eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
595689eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
595789eabcffSMatthew G. Knepley          */
5958e327e467SRezgar Shakeri         if (continuous) {
595989eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
596089eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
596189eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
596289eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
596389eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
596489eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
596589eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
596689eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
596789eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
596889eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
596989eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
597089eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
597189eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
597289eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
597389eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
597489eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
597589eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
597689eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
597789eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
597889eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
597989eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
598089eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
598189eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
598289eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
598389eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
598489eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
598589eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
598689eabcffSMatthew G. Knepley           PetscInt       o, n;
598789eabcffSMatthew G. Knepley 
598889eabcffSMatthew G. Knepley           /* Bottom Slice */
598989eabcffSMatthew G. Knepley           /*   bottom */
599089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
59919371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
59929371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
599389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
599489eabcffSMatthew G. Knepley           /*   middle */
599589eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
599689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
59979371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
59989371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
59999371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
60009371c9d4SSatish Balay             }
600189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
60023194fc30SMatthew G. Knepley           }
600389eabcffSMatthew G. Knepley           /*   top */
600489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
60059371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
60069371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
600789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
600889eabcffSMatthew G. Knepley 
600989eabcffSMatthew G. Knepley           /* Middle Slice */
601089eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
601189eabcffSMatthew G. Knepley             /*   bottom */
601289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
60139371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
60149371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
601589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
601689eabcffSMatthew G. Knepley             /*   middle */
601789eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
601889eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
60199371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
60209371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
602189eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
602289eabcffSMatthew G. Knepley             }
602389eabcffSMatthew G. Knepley             /*   top */
602489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
60259371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
60269371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
602789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
602889eabcffSMatthew G. Knepley           }
602989eabcffSMatthew G. Knepley 
603089eabcffSMatthew G. Knepley           /* Top Slice */
603189eabcffSMatthew G. Knepley           /*   bottom */
603289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
60339371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
60349371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
603589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
603689eabcffSMatthew G. Knepley           /*   middle */
603789eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
603889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
60399371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
60409371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
604189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
604289eabcffSMatthew G. Knepley           }
604389eabcffSMatthew G. Knepley           /*   top */
604489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
60459371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
60469371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
604789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
604889eabcffSMatthew G. Knepley 
604989eabcffSMatthew G. Knepley           foffset = offset;
6050e327e467SRezgar Shakeri         } else {
60515f82726aSMatthew G. Knepley           PetscInt dof;
60525f82726aSMatthew G. Knepley 
60535f82726aSMatthew G. Knepley           PetscCall(GetFieldSize_Private(d, k, tensor, &dof));
60545f82726aSMatthew G. Knepley           for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset;
60555f82726aSMatthew G. Knepley           foffset = offset;
605689eabcffSMatthew G. Knepley         }
605789eabcffSMatthew G. Knepley         break;
6058d71ae5a4SJacob Faibussowitsch       default:
6059d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
606089eabcffSMatthew G. Knepley       }
606189eabcffSMatthew G. Knepley     }
606263a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
60633194fc30SMatthew G. Knepley     /* Check permutation */
60643194fc30SMatthew G. Knepley     {
60653194fc30SMatthew G. Knepley       PetscInt *check;
60663194fc30SMatthew G. Knepley 
60679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
60681dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
60691dca8a05SBarry Smith         check[i] = -1;
60701dca8a05SBarry 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]);
60711dca8a05SBarry Smith       }
60723194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
60731dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
60749566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
60753194fc30SMatthew G. Knepley     }
60769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
6077a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
6078a05c9aa3SJed Brown       PetscInt *loc_perm;
60799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
6080a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
6081a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
6082a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
6083a05c9aa3SJed Brown       }
60849566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
6085a05c9aa3SJed Brown     }
6086bb197d40SJed Brown   }
60873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60883194fc30SMatthew G. Knepley }
60893194fc30SMatthew G. Knepley 
6090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
6091d71ae5a4SJacob Faibussowitsch {
6092e071409bSToby Isaac   PetscDS  prob;
6093e071409bSToby Isaac   PetscInt depth, Nf, h;
6094e071409bSToby Isaac   DMLabel  label;
6095e071409bSToby Isaac 
6096e071409bSToby Isaac   PetscFunctionBeginHot;
60979566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
6098e071409bSToby Isaac   Nf      = prob->Nf;
6099e071409bSToby Isaac   label   = dm->depthLabel;
6100e071409bSToby Isaac   *dspace = NULL;
6101e071409bSToby Isaac   if (field < Nf) {
6102e071409bSToby Isaac     PetscObject disc = prob->disc[field];
6103e071409bSToby Isaac 
6104e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
6105e071409bSToby Isaac       PetscDualSpace dsp;
6106e071409bSToby Isaac 
61079566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
61089566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
61099566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
6110e071409bSToby Isaac       h = depth - 1 - h;
6111e071409bSToby Isaac       if (h) {
61129566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
6113e071409bSToby Isaac       } else {
6114e071409bSToby Isaac         *dspace = dsp;
6115e071409bSToby Isaac       }
6116e071409bSToby Isaac     }
6117e071409bSToby Isaac   }
61183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6119e071409bSToby Isaac }
6120e071409bSToby Isaac 
6121d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6122d71ae5a4SJacob Faibussowitsch {
612328351e22SJed Brown   PetscScalar       *array;
612428351e22SJed Brown   const PetscScalar *vArray;
6125d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
61261a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
6127552f7358SJed Brown 
61281b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61333f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
61349df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
61359df71ca4SMatthew G. Knepley       PetscInt dof;
6136d9917b9dSMatthew G. Knepley 
61379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
61389df71ca4SMatthew G. Knepley       size += dof;
61399df71ca4SMatthew G. Knepley     }
61409df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
61419df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
61422a3aaacfSMatthew G. Knepley       PetscInt       dof;
61435a1bb5cfSMatthew G. Knepley 
61445a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
61459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
61465a1bb5cfSMatthew G. Knepley       size += dof;
61475a1bb5cfSMatthew G. Knepley     }
61483f7cbbe7SMatthew G. Knepley     if (!values) {
61493f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
61503ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
61513f7cbbe7SMatthew G. Knepley     }
61529566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
6153982e9ed1SMatthew G. Knepley   } else {
6154982e9ed1SMatthew G. Knepley     array = *values;
6155982e9ed1SMatthew G. Knepley   }
61569df71ca4SMatthew G. Knepley   size = 0;
615728351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
61589df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
61599df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
616028351e22SJed Brown     const PetscScalar *varr;
6161d9917b9dSMatthew G. Knepley 
61629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
61639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
61648e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
6165ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61669df71ca4SMatthew G. Knepley     size += dof;
61679df71ca4SMatthew G. Knepley   }
61689df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
61699df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
61709df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
61715a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
617228351e22SJed Brown     const PetscScalar *varr;
61735a1bb5cfSMatthew G. Knepley 
617452ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
61759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
61769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
61778e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
61785a1bb5cfSMatthew G. Knepley     if (o >= 0) {
6179ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
61805a1bb5cfSMatthew G. Knepley     } else {
6181ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
61825a1bb5cfSMatthew G. Knepley     }
61839df71ca4SMatthew G. Knepley     size += dof;
61845a1bb5cfSMatthew G. Knepley   }
618528351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
61869df71ca4SMatthew G. Knepley   if (!*values) {
61875a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
61885a1bb5cfSMatthew G. Knepley     *values = array;
61899df71ca4SMatthew G. Knepley   } else {
619063a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
61918c312ff3SMatthew G. Knepley     *csize = size;
61929df71ca4SMatthew G. Knepley   }
61933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61945a1bb5cfSMatthew G. Knepley }
6195d9917b9dSMatthew G. Knepley 
619627f02ce8SMatthew G. Knepley /* Compress out points not in the section */
6197d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
6198d71ae5a4SJacob Faibussowitsch {
619927f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
620027f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
620127f02ce8SMatthew G. Knepley 
62029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
620327f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
620427f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
620527f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
620627f02ce8SMatthew G. Knepley       points[q * 2]     = r;
620727f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
620827f02ce8SMatthew G. Knepley       ++q;
620927f02ce8SMatthew G. Knepley     }
621027f02ce8SMatthew G. Knepley   }
621127f02ce8SMatthew G. Knepley   *numPoints = q;
62123ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
621327f02ce8SMatthew G. Knepley }
621427f02ce8SMatthew G. Knepley 
621597529cf3SJed Brown /* Compressed closure does not apply closure permutation */
621607218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6217d71ae5a4SJacob Faibussowitsch {
621827f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
6219923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
6220923c78e0SToby Isaac 
6221923c78e0SToby Isaac   PetscFunctionBeginHot;
62229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
622307218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
6224923c78e0SToby Isaac     PetscInt dof, off;
6225923c78e0SToby Isaac 
62269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
62279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
62289566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
6229923c78e0SToby Isaac     np  = dof / 2;
62308e3a54c0SPierre Jolivet     pts = PetscSafePointerPlusOffset((PetscInt *)cla, off);
623127f02ce8SMatthew G. Knepley   } else {
623207218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
62339566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
6234923c78e0SToby Isaac   }
6235923c78e0SToby Isaac   *numPoints = np;
6236923c78e0SToby Isaac   *points    = pts;
6237923c78e0SToby Isaac   *clp       = cla;
62383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6239923c78e0SToby Isaac }
6240923c78e0SToby Isaac 
6241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
6242d71ae5a4SJacob Faibussowitsch {
6243923c78e0SToby Isaac   PetscFunctionBeginHot;
6244923c78e0SToby Isaac   if (!*clPoints) {
62459566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
6246923c78e0SToby Isaac   } else {
62479566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
6248923c78e0SToby Isaac   }
6249923c78e0SToby Isaac   *numPoints = 0;
6250923c78e0SToby Isaac   *points    = NULL;
6251923c78e0SToby Isaac   *clSec     = NULL;
6252923c78e0SToby Isaac   *clPoints  = NULL;
6253923c78e0SToby Isaac   *clp       = NULL;
62543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6255923c78e0SToby Isaac }
6256923c78e0SToby Isaac 
6257d71ae5a4SJacob 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[])
6258d71ae5a4SJacob Faibussowitsch {
62591a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
626097e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
626197e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
62621a271a75SMatthew G. Knepley 
62631a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6264fe02ba77SJed Brown   *size = 0;
62659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
626697e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
626797e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
626897e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
626997e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
62701a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
62711a271a75SMatthew G. Knepley     const PetscScalar *varr;
62721a271a75SMatthew G. Knepley 
62739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
62749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
62758e3a54c0SPierre Jolivet     varr = PetscSafePointerPlusOffset(vArray, off);
627697e99dd9SToby Isaac     if (clperm) {
627797e99dd9SToby Isaac       if (perm) {
627897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
62791a271a75SMatthew G. Knepley       } else {
628097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
628197e99dd9SToby Isaac       }
628297e99dd9SToby Isaac       if (flip) {
628397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
628497e99dd9SToby Isaac       }
628597e99dd9SToby Isaac     } else {
628697e99dd9SToby Isaac       if (perm) {
628797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
628897e99dd9SToby Isaac       } else {
628997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
629097e99dd9SToby Isaac       }
629197e99dd9SToby Isaac       if (flip) {
629297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
62931a271a75SMatthew G. Knepley       }
62941a271a75SMatthew G. Knepley     }
629597e99dd9SToby Isaac     offset += dof;
629697e99dd9SToby Isaac   }
62979566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
62981a271a75SMatthew G. Knepley   *size = offset;
62993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63001a271a75SMatthew G. Knepley }
63011a271a75SMatthew G. Knepley 
6302d71ae5a4SJacob 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[])
6303d71ae5a4SJacob Faibussowitsch {
63041a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
63051a271a75SMatthew G. Knepley 
63061a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
6307fe02ba77SJed Brown   *size = 0;
63081a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
630997e99dd9SToby Isaac     PetscInt            p;
631097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
631197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63121a271a75SMatthew G. Knepley 
63139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
631497e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
631597e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
631697e99dd9SToby Isaac       PetscInt           fdof, foff, b;
63171a271a75SMatthew G. Knepley       const PetscScalar *varr;
631897e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
631997e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
63201a271a75SMatthew G. Knepley 
63219566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63231a271a75SMatthew G. Knepley       varr = &vArray[foff];
632497e99dd9SToby Isaac       if (clperm) {
63259371c9d4SSatish Balay         if (perm) {
6326ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
63271a271a75SMatthew G. Knepley         } else {
6328ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
63299371c9d4SSatish Balay         }
63309371c9d4SSatish Balay         if (flip) {
6331ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
63329371c9d4SSatish Balay         }
63339371c9d4SSatish Balay       } else {
63349371c9d4SSatish Balay         if (perm) {
6335ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
63369371c9d4SSatish Balay         } else {
6337ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
63389371c9d4SSatish Balay         }
63399371c9d4SSatish Balay         if (flip) {
6340ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
63419371c9d4SSatish Balay         }
63421a271a75SMatthew G. Knepley       }
634397e99dd9SToby Isaac       offset += fdof;
63441a271a75SMatthew G. Knepley     }
63459566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
63461a271a75SMatthew G. Knepley   }
63471a271a75SMatthew G. Knepley   *size = offset;
63483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63491a271a75SMatthew G. Knepley }
63501a271a75SMatthew G. Knepley 
6351e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
635207218a29SMatthew G. Knepley {
635307218a29SMatthew G. Knepley   PetscSection    clSection;
635407218a29SMatthew G. Knepley   IS              clPoints;
635507218a29SMatthew G. Knepley   PetscInt       *points = NULL;
6356e8e188d2SZach Atkins   const PetscInt *clp, *perm = NULL;
635707218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
635807218a29SMatthew G. Knepley 
635907218a29SMatthew G. Knepley   PetscFunctionBeginHot;
636007218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
636107218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
636207218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6363e8e188d2SZach Atkins   PetscValidHeaderSpecific(v, VEC_CLASSID, 4);
636407218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
636507218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
636607218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
636707218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
636807218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
636907218a29SMatthew G. Knepley   }
637007218a29SMatthew G. Knepley   /* Get points */
637107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
637207218a29SMatthew G. Knepley   /* Get sizes */
637307218a29SMatthew G. Knepley   asize = 0;
637407218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
637507218a29SMatthew G. Knepley     PetscInt dof;
637607218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
637707218a29SMatthew G. Knepley     asize += dof;
637807218a29SMatthew G. Knepley   }
637907218a29SMatthew G. Knepley   if (values) {
638007218a29SMatthew G. Knepley     const PetscScalar *vArray;
638107218a29SMatthew G. Knepley     PetscInt           size;
638207218a29SMatthew G. Knepley 
638307218a29SMatthew G. Knepley     if (*values) {
638407218a29SMatthew 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);
638507218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
6386e8e188d2SZach Atkins     if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
638707218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
638807218a29SMatthew G. Knepley     /* Get values */
638907218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
639007218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
639107218a29SMatthew 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);
639207218a29SMatthew G. Knepley     /* Cleanup array */
639307218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
639407218a29SMatthew G. Knepley   }
639507218a29SMatthew G. Knepley   if (csize) *csize = asize;
639607218a29SMatthew G. Knepley   /* Cleanup points */
639707218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
639807218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
639907218a29SMatthew G. Knepley }
640007218a29SMatthew G. Knepley 
6401552f7358SJed Brown /*@C
6402552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6403552f7358SJed Brown 
6404552f7358SJed Brown   Not collective
6405552f7358SJed Brown 
6406552f7358SJed Brown   Input Parameters:
6407a1cb98faSBarry Smith + dm      - The `DM`
640820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6409552f7358SJed Brown . v       - The local vector
6410a1cb98faSBarry Smith - point   - The point in the `DM`
6411552f7358SJed Brown 
64126b867d5aSJose E. Roman   Input/Output Parameters:
641320f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
641420f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
641520f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
641622c1ee49SMatthew G. Knepley 
6417552f7358SJed Brown   Level: intermediate
6418552f7358SJed Brown 
6419a1cb98faSBarry Smith   Notes:
642020f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6421a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6422a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6423a1cb98faSBarry Smith 
6424a1cb98faSBarry Smith   A typical use could be
6425a1cb98faSBarry Smith .vb
6426a1cb98faSBarry Smith    values = NULL;
6427a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6428a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6429a1cb98faSBarry Smith      <Compute on closure>
6430a1cb98faSBarry Smith    }
6431a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6432a1cb98faSBarry Smith .ve
6433a1cb98faSBarry Smith   or
6434a1cb98faSBarry Smith .vb
6435a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6436a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6437a1cb98faSBarry Smith      clSize = clMaxSize;
6438a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6439a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6440a1cb98faSBarry Smith        <Compute on closure>
6441a1cb98faSBarry Smith      }
6442a1cb98faSBarry Smith    }
6443a1cb98faSBarry Smith    PetscFree(values);
6444a1cb98faSBarry Smith .ve
6445a1cb98faSBarry Smith 
644660225df5SJacob Faibussowitsch   Fortran Notes:
644720f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6448a1cb98faSBarry Smith 
64491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6450552f7358SJed Brown @*/
6451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6452d71ae5a4SJacob Faibussowitsch {
6453d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
6454e8e188d2SZach Atkins   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values));
64553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6456552f7358SJed Brown }
6457552f7358SJed Brown 
6458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6459d71ae5a4SJacob Faibussowitsch {
6460e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6461e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6462e5c487bfSMatthew G. Knepley   IS                 clPoints;
6463e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6464e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6465e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6466c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6467c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6468e5c487bfSMatthew G. Knepley 
6469e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6470e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64719566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6472e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6473e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
64759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
64769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6477e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
64789566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
64793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6480e5c487bfSMatthew G. Knepley   }
6481e5c487bfSMatthew G. Knepley   /* Get points */
648207218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6483c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6484c459fbc1SJed Brown     PetscInt dof;
64859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6486c459fbc1SJed Brown     clsize += dof;
6487c459fbc1SJed Brown   }
64889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6489e5c487bfSMatthew G. Knepley   /* Filter points */
6490e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6491e5c487bfSMatthew G. Knepley     PetscInt dep;
6492e5c487bfSMatthew G. Knepley 
64939566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6494e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6495e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6496e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6497e5c487bfSMatthew G. Knepley     ++Np;
6498e5c487bfSMatthew G. Knepley   }
6499e5c487bfSMatthew G. Knepley   /* Get array */
6500e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6501e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6502e5c487bfSMatthew G. Knepley 
6503e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
65049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6505e5c487bfSMatthew G. Knepley       asize += dof;
6506e5c487bfSMatthew G. Knepley     }
6507e5c487bfSMatthew G. Knepley     if (!values) {
65089566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6509e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
65103ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6511e5c487bfSMatthew G. Knepley     }
65129566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6513e5c487bfSMatthew G. Knepley   } else {
6514e5c487bfSMatthew G. Knepley     array = *values;
6515e5c487bfSMatthew G. Knepley   }
65169566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6517e5c487bfSMatthew G. Knepley   /* Get values */
65189566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
65199566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6520e5c487bfSMatthew G. Knepley   /* Cleanup points */
65219566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6522e5c487bfSMatthew G. Knepley   /* Cleanup array */
65239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6524e5c487bfSMatthew G. Knepley   if (!*values) {
6525e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6526e5c487bfSMatthew G. Knepley     *values = array;
6527e5c487bfSMatthew G. Knepley   } else {
652863a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6529e5c487bfSMatthew G. Knepley     *csize = size;
6530e5c487bfSMatthew G. Knepley   }
65313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6532e5c487bfSMatthew G. Knepley }
6533e5c487bfSMatthew G. Knepley 
6534552f7358SJed Brown /*@C
6535552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6536552f7358SJed Brown 
6537552f7358SJed Brown   Not collective
6538552f7358SJed Brown 
6539552f7358SJed Brown   Input Parameters:
6540a1cb98faSBarry Smith + dm      - The `DM`
654120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6542552f7358SJed Brown . v       - The local vector
6543a1cb98faSBarry Smith . point   - The point in the `DM`
654420f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6545552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6546552f7358SJed Brown 
6547552f7358SJed Brown   Level: intermediate
6548552f7358SJed Brown 
6549a1cb98faSBarry Smith   Note:
655020f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6551a1cb98faSBarry Smith 
655260225df5SJacob Faibussowitsch   Fortran Notes:
655320f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6554a1cb98faSBarry Smith 
65551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6556552f7358SJed Brown @*/
6557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6558d71ae5a4SJacob Faibussowitsch {
6559552f7358SJed Brown   PetscInt size = 0;
6560552f7358SJed Brown 
6561552f7358SJed Brown   PetscFunctionBegin;
6562552f7358SJed Brown   /* Should work without recalculating size */
65639566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6564c9fdaa05SMatthew G. Knepley   *values = NULL;
65653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6566552f7358SJed Brown }
6567552f7358SJed Brown 
6568d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6569d71ae5a4SJacob Faibussowitsch {
65709371c9d4SSatish Balay   *x += y;
65719371c9d4SSatish Balay }
6572d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6573d71ae5a4SJacob Faibussowitsch {
65749371c9d4SSatish Balay   *x = y;
65759371c9d4SSatish Balay }
6576552f7358SJed Brown 
6577d71ae5a4SJacob 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[])
6578d71ae5a4SJacob Faibussowitsch {
6579552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6580552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6581552f7358SJed Brown   PetscScalar    *a;
6582552f7358SJed Brown   PetscInt        off, cind = 0, k;
6583552f7358SJed Brown 
6584552f7358SJed Brown   PetscFunctionBegin;
65859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
65869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6587552f7358SJed Brown   a = &array[off];
6588552f7358SJed Brown   if (!cdof || setBC) {
658997e99dd9SToby Isaac     if (clperm) {
65909371c9d4SSatish Balay       if (perm) {
6591ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6592552f7358SJed Brown       } else {
6593ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
65949371c9d4SSatish Balay       }
65959371c9d4SSatish Balay     } else {
65969371c9d4SSatish Balay       if (perm) {
6597ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
65989371c9d4SSatish Balay       } else {
6599ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
66009371c9d4SSatish Balay       }
6601552f7358SJed Brown     }
6602552f7358SJed Brown   } else {
66039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
660497e99dd9SToby Isaac     if (clperm) {
66059371c9d4SSatish Balay       if (perm) {
66069371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
66079371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66089371c9d4SSatish Balay             ++cind;
66099371c9d4SSatish Balay             continue;
66109371c9d4SSatish Balay           }
661197e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6612552f7358SJed Brown         }
6613552f7358SJed Brown       } else {
6614552f7358SJed Brown         for (k = 0; k < dof; ++k) {
66159371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66169371c9d4SSatish Balay             ++cind;
66179371c9d4SSatish Balay             continue;
66189371c9d4SSatish Balay           }
661997e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
662097e99dd9SToby Isaac         }
662197e99dd9SToby Isaac       }
662297e99dd9SToby Isaac     } else {
662397e99dd9SToby Isaac       if (perm) {
662497e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66259371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66269371c9d4SSatish Balay             ++cind;
66279371c9d4SSatish Balay             continue;
66289371c9d4SSatish Balay           }
662997e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
663097e99dd9SToby Isaac         }
663197e99dd9SToby Isaac       } else {
663297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
66339371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
66349371c9d4SSatish Balay             ++cind;
66359371c9d4SSatish Balay             continue;
66369371c9d4SSatish Balay           }
663797e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
663897e99dd9SToby Isaac         }
6639552f7358SJed Brown       }
6640552f7358SJed Brown     }
6641552f7358SJed Brown   }
66423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6643552f7358SJed Brown }
6644552f7358SJed Brown 
6645d71ae5a4SJacob 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[])
6646d71ae5a4SJacob Faibussowitsch {
6647a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6648a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6649a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6650a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6651a5e93ea8SMatthew G. Knepley 
6652a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
66539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
66549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6655a5e93ea8SMatthew G. Knepley   a = &array[off];
6656a5e93ea8SMatthew G. Knepley   if (cdof) {
66579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
665897e99dd9SToby Isaac     if (clperm) {
665997e99dd9SToby Isaac       if (perm) {
6660a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6661a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
666297e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
666397e99dd9SToby Isaac             cind++;
6664a5e93ea8SMatthew G. Knepley           }
6665a5e93ea8SMatthew G. Knepley         }
6666a5e93ea8SMatthew G. Knepley       } else {
6667a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6668a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
666997e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
667097e99dd9SToby Isaac             cind++;
667197e99dd9SToby Isaac           }
667297e99dd9SToby Isaac         }
667397e99dd9SToby Isaac       }
667497e99dd9SToby Isaac     } else {
667597e99dd9SToby Isaac       if (perm) {
667697e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
667797e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
667897e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
667997e99dd9SToby Isaac             cind++;
668097e99dd9SToby Isaac           }
668197e99dd9SToby Isaac         }
668297e99dd9SToby Isaac       } else {
668397e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
668497e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
668597e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
668697e99dd9SToby Isaac             cind++;
668797e99dd9SToby Isaac           }
6688a5e93ea8SMatthew G. Knepley         }
6689a5e93ea8SMatthew G. Knepley       }
6690a5e93ea8SMatthew G. Knepley     }
6691a5e93ea8SMatthew G. Knepley   }
66923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6693a5e93ea8SMatthew G. Knepley }
6694a5e93ea8SMatthew G. Knepley 
6695d71ae5a4SJacob 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[])
6696d71ae5a4SJacob Faibussowitsch {
6697552f7358SJed Brown   PetscScalar    *a;
66981a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
66991a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
670097e99dd9SToby Isaac   PetscInt        cind = 0, b;
6701552f7358SJed Brown 
6702552f7358SJed Brown   PetscFunctionBegin;
67039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67061a271a75SMatthew G. Knepley   a = &array[foff];
6707552f7358SJed Brown   if (!fcdof || setBC) {
670897e99dd9SToby Isaac     if (clperm) {
67099371c9d4SSatish Balay       if (perm) {
6710ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6711552f7358SJed Brown       } else {
6712ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
67139371c9d4SSatish Balay       }
67149371c9d4SSatish Balay     } else {
67159371c9d4SSatish Balay       if (perm) {
6716ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
67179371c9d4SSatish Balay       } else {
6718ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
67199371c9d4SSatish Balay       }
6720552f7358SJed Brown     }
6721552f7358SJed Brown   } else {
67229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
672397e99dd9SToby Isaac     if (clperm) {
672497e99dd9SToby Isaac       if (perm) {
672597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67269371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67279371c9d4SSatish Balay             ++cind;
67289371c9d4SSatish Balay             continue;
67299371c9d4SSatish Balay           }
673097e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6731552f7358SJed Brown         }
6732552f7358SJed Brown       } else {
673397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67349371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67359371c9d4SSatish Balay             ++cind;
67369371c9d4SSatish Balay             continue;
67379371c9d4SSatish Balay           }
673897e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
673997e99dd9SToby Isaac         }
674097e99dd9SToby Isaac       }
674197e99dd9SToby Isaac     } else {
674297e99dd9SToby Isaac       if (perm) {
674397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67449371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67459371c9d4SSatish Balay             ++cind;
67469371c9d4SSatish Balay             continue;
67479371c9d4SSatish Balay           }
674897e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
674997e99dd9SToby Isaac         }
675097e99dd9SToby Isaac       } else {
675197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
67529371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
67539371c9d4SSatish Balay             ++cind;
67549371c9d4SSatish Balay             continue;
67559371c9d4SSatish Balay           }
675697e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6757552f7358SJed Brown         }
6758552f7358SJed Brown       }
6759552f7358SJed Brown     }
6760552f7358SJed Brown   }
67611a271a75SMatthew G. Knepley   *offset += fdof;
67623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6763552f7358SJed Brown }
6764552f7358SJed Brown 
6765d71ae5a4SJacob 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[])
6766d71ae5a4SJacob Faibussowitsch {
6767a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
67681a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
67691a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67705da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6771ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6772a5e93ea8SMatthew G. Knepley 
6773a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
67749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
67759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
67779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
67781a271a75SMatthew G. Knepley   a = &array[foff];
6779a5e93ea8SMatthew G. Knepley   if (fcdof) {
6780ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
67819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
678297e99dd9SToby Isaac     if (clperm) {
678397e99dd9SToby Isaac       if (perm) {
6784ba322698SMatthew G. Knepley         if (comps) {
6785ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6786ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
67879371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
67889371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
67899371c9d4SSatish Balay               ncSet = PETSC_TRUE;
67909371c9d4SSatish Balay             }
67919371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
67929371c9d4SSatish Balay               ++cind;
67939371c9d4SSatish Balay               fcSet = PETSC_TRUE;
67949371c9d4SSatish Balay             }
6795ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6796ba322698SMatthew G. Knepley           }
6797ba322698SMatthew G. Knepley         } else {
679897e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
679997e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
680097e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6801a5e93ea8SMatthew G. Knepley               ++cind;
6802a5e93ea8SMatthew G. Knepley             }
6803a5e93ea8SMatthew G. Knepley           }
6804ba322698SMatthew G. Knepley         }
6805ba322698SMatthew G. Knepley       } else {
6806ba322698SMatthew G. Knepley         if (comps) {
6807ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6808ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68099371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68109371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68119371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68129371c9d4SSatish Balay             }
68139371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68149371c9d4SSatish Balay               ++cind;
68159371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68169371c9d4SSatish Balay             }
6817ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6818ba322698SMatthew G. Knepley           }
6819a5e93ea8SMatthew G. Knepley         } else {
682097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
682197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
682297e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
682397e99dd9SToby Isaac               ++cind;
682497e99dd9SToby Isaac             }
682597e99dd9SToby Isaac           }
682697e99dd9SToby Isaac         }
6827ba322698SMatthew G. Knepley       }
682897e99dd9SToby Isaac     } else {
682997e99dd9SToby Isaac       if (perm) {
6830ba322698SMatthew G. Knepley         if (comps) {
6831ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6832ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68339371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68349371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68359371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68369371c9d4SSatish Balay             }
68379371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68389371c9d4SSatish Balay               ++cind;
68399371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68409371c9d4SSatish Balay             }
6841ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6842ba322698SMatthew G. Knepley           }
6843ba322698SMatthew G. Knepley         } else {
684497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
684597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
684697e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
684797e99dd9SToby Isaac               ++cind;
684897e99dd9SToby Isaac             }
684997e99dd9SToby Isaac           }
6850ba322698SMatthew G. Knepley         }
6851ba322698SMatthew G. Knepley       } else {
6852ba322698SMatthew G. Knepley         if (comps) {
6853ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6854ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
68559371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
68569371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
68579371c9d4SSatish Balay               ncSet = PETSC_TRUE;
68589371c9d4SSatish Balay             }
68599371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
68609371c9d4SSatish Balay               ++cind;
68619371c9d4SSatish Balay               fcSet = PETSC_TRUE;
68629371c9d4SSatish Balay             }
6863ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6864ba322698SMatthew G. Knepley           }
686597e99dd9SToby Isaac         } else {
686697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
686797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
686897e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6869a5e93ea8SMatthew G. Knepley               ++cind;
6870a5e93ea8SMatthew G. Knepley             }
6871a5e93ea8SMatthew G. Knepley           }
6872a5e93ea8SMatthew G. Knepley         }
6873a5e93ea8SMatthew G. Knepley       }
6874a5e93ea8SMatthew G. Knepley     }
6875ba322698SMatthew G. Knepley   }
68761a271a75SMatthew G. Knepley   *offset += fdof;
68773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6878a5e93ea8SMatthew G. Knepley }
6879a5e93ea8SMatthew G. Knepley 
6880d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6881d71ae5a4SJacob Faibussowitsch {
6882552f7358SJed Brown   PetscScalar    *array;
68831b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
68841b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6885552f7358SJed Brown 
68861b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
68879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
68889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
68899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
68909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
68919566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6892b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6893b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6894b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6895b6ebb6e6SMatthew G. Knepley 
68969371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
68979371c9d4SSatish Balay       dof = 0;
68989371c9d4SSatish Balay       continue;
68999371c9d4SSatish Balay     }
69009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6901b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6902b6ebb6e6SMatthew G. Knepley     {
6903b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6904b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6905b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6906b6ebb6e6SMatthew G. Knepley 
69079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
69089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6909b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6910b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6911b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6912ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6913b6ebb6e6SMatthew G. Knepley         } else {
6914ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6915b6ebb6e6SMatthew G. Knepley         }
6916b6ebb6e6SMatthew G. Knepley       } else {
69179566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6918b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6919b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69209371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69219371c9d4SSatish Balay               ++cind;
69229371c9d4SSatish Balay               continue;
69239371c9d4SSatish Balay             }
6924b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6925b6ebb6e6SMatthew G. Knepley           }
6926b6ebb6e6SMatthew G. Knepley         } else {
6927b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
69289371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
69299371c9d4SSatish Balay               ++cind;
69309371c9d4SSatish Balay               continue;
69319371c9d4SSatish Balay             }
6932b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6933b6ebb6e6SMatthew G. Knepley           }
6934b6ebb6e6SMatthew G. Knepley         }
6935b6ebb6e6SMatthew G. Knepley       }
6936b6ebb6e6SMatthew G. Knepley     }
6937b6ebb6e6SMatthew G. Knepley   }
69389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6940b6ebb6e6SMatthew G. Knepley }
69411b406b76SMatthew G. Knepley 
69421b406b76SMatthew G. Knepley /*@C
694320f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
69441b406b76SMatthew G. Knepley 
69451b406b76SMatthew G. Knepley   Not collective
69461b406b76SMatthew G. Knepley 
69471b406b76SMatthew G. Knepley   Input Parameters:
6948a1cb98faSBarry Smith + dm      - The `DM`
694920f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
69501b406b76SMatthew G. Knepley . v       - The local vector
695120f4b53cSBarry Smith . point   - The point in the `DM`
69521b406b76SMatthew G. Knepley . values  - The array of values
6953a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6954a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
69551b406b76SMatthew G. Knepley 
69561b406b76SMatthew G. Knepley   Level: intermediate
69571b406b76SMatthew G. Knepley 
69581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
69591b406b76SMatthew G. Knepley @*/
6960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6961d71ae5a4SJacob Faibussowitsch {
69621b406b76SMatthew G. Knepley   PetscSection    clSection;
69631b406b76SMatthew G. Knepley   IS              clPoints;
69641b406b76SMatthew G. Knepley   PetscScalar    *array;
69651b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
696627f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6967c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
69681b406b76SMatthew G. Knepley 
69691a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
69701b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
69719566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
69721a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
69731a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
69749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
69759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
69761b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
69779566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
69783ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
69791b406b76SMatthew G. Knepley   }
69801a271a75SMatthew G. Knepley   /* Get points */
698107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6982c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6983c459fbc1SJed Brown     PetscInt dof;
69849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6985c459fbc1SJed Brown     clsize += dof;
6986c459fbc1SJed Brown   }
69879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
69881a271a75SMatthew G. Knepley   /* Get array */
69899566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
69901a271a75SMatthew G. Knepley   /* Get values */
6991ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
699297e99dd9SToby Isaac     PetscInt offset = 0, f;
6993552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
699497e99dd9SToby Isaac       const PetscInt    **perms = NULL;
699597e99dd9SToby Isaac       const PetscScalar **flips = NULL;
699697e99dd9SToby Isaac 
69979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6998552f7358SJed Brown       switch (mode) {
6999552f7358SJed Brown       case INSERT_VALUES:
700097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
700197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
700297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
700397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70043ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
70059371c9d4SSatish Balay         }
70069371c9d4SSatish Balay         break;
7007552f7358SJed Brown       case INSERT_ALL_VALUES:
700897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
700997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
701097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
701197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70123ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
70139371c9d4SSatish Balay         }
70149371c9d4SSatish Balay         break;
7015a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
701697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
701797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
701897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
701997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70203ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
70219371c9d4SSatish Balay         }
70229371c9d4SSatish Balay         break;
7023552f7358SJed Brown       case ADD_VALUES:
702497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
702597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
702697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
702797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70283ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
70299371c9d4SSatish Balay         }
70309371c9d4SSatish Balay         break;
7031552f7358SJed Brown       case ADD_ALL_VALUES:
703297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
703397e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
703497e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
703597e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70363ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
70379371c9d4SSatish Balay         }
70389371c9d4SSatish Balay         break;
7039304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
704097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
704197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
704297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
704397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
70443ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
70459371c9d4SSatish Balay         }
70469371c9d4SSatish Balay         break;
7047d71ae5a4SJacob Faibussowitsch       default:
7048d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7049552f7358SJed Brown       }
70509566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
70511a271a75SMatthew G. Knepley     }
7052552f7358SJed Brown   } else {
70531a271a75SMatthew G. Knepley     PetscInt            dof, off;
705497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
705597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
70561a271a75SMatthew G. Knepley 
70579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
7058552f7358SJed Brown     switch (mode) {
7059552f7358SJed Brown     case INSERT_VALUES:
706097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
706197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
706297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
706397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70653ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
70669371c9d4SSatish Balay       }
70679371c9d4SSatish Balay       break;
7068552f7358SJed Brown     case INSERT_ALL_VALUES:
706997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
707097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
707197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
707297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70743ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
70759371c9d4SSatish Balay       }
70769371c9d4SSatish Balay       break;
7077a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
707897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
707997e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708097e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
708197e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70829566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70833ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
70849371c9d4SSatish Balay       }
70859371c9d4SSatish Balay       break;
7086552f7358SJed Brown     case ADD_VALUES:
708797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
708897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
708997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
70919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
70923ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
70939371c9d4SSatish Balay       }
70949371c9d4SSatish Balay       break;
7095552f7358SJed Brown     case ADD_ALL_VALUES:
709697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
709797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
709897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
709997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71013ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
71029371c9d4SSatish Balay       }
71039371c9d4SSatish Balay       break;
7104304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
710597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
710697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
710797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
710897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
71099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
71103ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
71119371c9d4SSatish Balay       }
71129371c9d4SSatish Balay       break;
7113d71ae5a4SJacob Faibussowitsch     default:
7114d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7115552f7358SJed Brown     }
71169566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
7117552f7358SJed Brown   }
71181a271a75SMatthew G. Knepley   /* Cleanup points */
71199566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
71201a271a75SMatthew G. Knepley   /* Cleanup array */
71219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
71223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7123552f7358SJed Brown }
7124552f7358SJed Brown 
71255f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
7126d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
7127d71ae5a4SJacob Faibussowitsch {
71285f790a90SMatthew G. Knepley   PetscFunctionBegin;
712911cc89d2SBarry Smith   *contains = PETSC_TRUE;
71305f790a90SMatthew G. Knepley   if (label) {
7131d6177c40SToby Isaac     PetscInt fdof;
71325f790a90SMatthew G. Knepley 
713311cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
713411cc89d2SBarry Smith     if (!*contains) {
71359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71365f790a90SMatthew G. Knepley       *offset += fdof;
71373ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
71385f790a90SMatthew G. Knepley     }
71395f790a90SMatthew G. Knepley   }
71403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71415f790a90SMatthew G. Knepley }
71425f790a90SMatthew G. Knepley 
714397529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
7144d71ae5a4SJacob 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)
7145d71ae5a4SJacob Faibussowitsch {
7146e07394fbSMatthew G. Knepley   PetscSection    clSection;
7147e07394fbSMatthew G. Knepley   IS              clPoints;
7148e07394fbSMatthew G. Knepley   PetscScalar    *array;
7149e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
715097529cf3SJed Brown   const PetscInt *clp;
7151e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
715297e99dd9SToby Isaac   PetscInt        offset = 0, f;
7153e07394fbSMatthew G. Knepley 
7154e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
7155e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
71569566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
7157e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7158e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
71599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7160e07394fbSMatthew G. Knepley   /* Get points */
716107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
7162e07394fbSMatthew G. Knepley   /* Get array */
71639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
7164e07394fbSMatthew G. Knepley   /* Get values */
7165e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
716697e99dd9SToby Isaac     const PetscInt    **perms = NULL;
716797e99dd9SToby Isaac     const PetscScalar **flips = NULL;
716811cc89d2SBarry Smith     PetscBool           contains;
716997e99dd9SToby Isaac 
7170e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
7171e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
7172e07394fbSMatthew G. Knepley         PetscInt fdof;
71739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
7174e07394fbSMatthew G. Knepley         offset += fdof;
7175e07394fbSMatthew G. Knepley       }
7176e07394fbSMatthew G. Knepley       continue;
7177e07394fbSMatthew G. Knepley     }
71789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7179e07394fbSMatthew G. Knepley     switch (mode) {
7180e07394fbSMatthew G. Knepley     case INSERT_VALUES:
718197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
718297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
718397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
718497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
718511cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
718611cc89d2SBarry Smith         if (!contains) continue;
71879566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
71889371c9d4SSatish Balay       }
71899371c9d4SSatish Balay       break;
7190e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
719197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
719297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
719397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
719497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
719511cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
719611cc89d2SBarry Smith         if (!contains) continue;
71979566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
71989371c9d4SSatish Balay       }
71999371c9d4SSatish Balay       break;
7200e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
720197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
720297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
720397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
720497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
720511cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
720611cc89d2SBarry Smith         if (!contains) continue;
72079566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
72089371c9d4SSatish Balay       }
72099371c9d4SSatish Balay       break;
7210e07394fbSMatthew G. Knepley     case ADD_VALUES:
721197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
721297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
721397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
721497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
721511cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
721611cc89d2SBarry Smith         if (!contains) continue;
72179566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
72189371c9d4SSatish Balay       }
72199371c9d4SSatish Balay       break;
7220e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
722197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
722297e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
722397e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
722497e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
722511cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
722611cc89d2SBarry Smith         if (!contains) continue;
72279566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
72289371c9d4SSatish Balay       }
72299371c9d4SSatish Balay       break;
7230d71ae5a4SJacob Faibussowitsch     default:
7231d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
7232e07394fbSMatthew G. Knepley     }
72339566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
7234e07394fbSMatthew G. Knepley   }
7235e07394fbSMatthew G. Knepley   /* Cleanup points */
72369566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
7237e07394fbSMatthew G. Knepley   /* Cleanup array */
72389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
72393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7240e07394fbSMatthew G. Knepley }
7241e07394fbSMatthew G. Knepley 
7242d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
7243d71ae5a4SJacob Faibussowitsch {
7244552f7358SJed Brown   PetscMPIInt rank;
7245552f7358SJed Brown   PetscInt    i, j;
7246552f7358SJed Brown 
7247552f7358SJed Brown   PetscFunctionBegin;
72489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
724963a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
725063a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
725163a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
7252b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
72533ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
7254b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
72559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
7256b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
7257519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
72589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
7259552f7358SJed Brown #else
72609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
7261552f7358SJed Brown #endif
7262552f7358SJed Brown     }
72639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
7264552f7358SJed Brown   }
72653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7266552f7358SJed Brown }
7267552f7358SJed Brown 
726805586334SMatthew G. Knepley /*
726905586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
727005586334SMatthew G. Knepley 
727105586334SMatthew G. Knepley   Input Parameters:
727205586334SMatthew G. Knepley + section - The section for this data layout
727336fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
727405586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
727505586334SMatthew G. Knepley . off     - The global offset of this point
727605586334SMatthew G. Knepley . loff    - The local offset of each field
7277a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
727805586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
727905586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
728005586334SMatthew G. Knepley 
728105586334SMatthew G. Knepley   Output Parameter:
728205586334SMatthew G. Knepley . indices - Indices for dofs on this point
728305586334SMatthew G. Knepley 
728405586334SMatthew G. Knepley   Level: developer
728505586334SMatthew G. Knepley 
728605586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
728705586334SMatthew G. Knepley */
7288d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
7289d71ae5a4SJacob Faibussowitsch {
7290e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
7291552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7292552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7293552f7358SJed Brown   PetscInt        cind = 0, k;
7294552f7358SJed Brown 
7295552f7358SJed Brown   PetscFunctionBegin;
729608401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
72979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
72989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
7299552f7358SJed Brown   if (!cdof || setBC) {
730005586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
730105586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
730205586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
730305586334SMatthew G. Knepley 
730405586334SMatthew G. Knepley       indices[ind] = off + k;
7305552f7358SJed Brown     }
7306552f7358SJed Brown   } else {
73079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
73084acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
730905586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
731005586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
731105586334SMatthew G. Knepley 
73124acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
73134acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
731405586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
73154acb8e1eSToby Isaac         ++cind;
73164acb8e1eSToby Isaac       } else {
731736fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7318552f7358SJed Brown       }
7319552f7358SJed Brown     }
7320552f7358SJed Brown   }
7321e6ccafaeSMatthew G Knepley   *loff += dof;
73223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7323552f7358SJed Brown }
7324552f7358SJed Brown 
73257e29afd2SMatthew G. Knepley /*
732636fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
73277e29afd2SMatthew G. Knepley 
732836fa2b79SJed Brown  Input Parameters:
732936fa2b79SJed Brown + section - a section (global or local)
733020f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
733136fa2b79SJed Brown . point - point within section
733236fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
733336fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
733436fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
733536fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
733636fa2b79SJed Brown . permsoff - offset
733736fa2b79SJed Brown - indperm - index permutation
733836fa2b79SJed Brown 
733936fa2b79SJed Brown  Output Parameter:
734036fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
734136fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
734236fa2b79SJed Brown 
734336fa2b79SJed Brown  Notes:
734436fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
734536fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
734636fa2b79SJed Brown  in the local vector.
734736fa2b79SJed Brown 
734836fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
734936fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
735036fa2b79SJed Brown 
735136fa2b79SJed Brown  Developer Note:
735236fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
735336fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
735436fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
735536fa2b79SJed Brown 
735636fa2b79SJed Brown  Example:
735736fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
735836fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
735936fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
736036fa2b79SJed 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.
736136fa2b79SJed Brown 
736236fa2b79SJed Brown  Level: developer
73637e29afd2SMatthew G. Knepley */
7364d71ae5a4SJacob 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[])
7365d71ae5a4SJacob Faibussowitsch {
7366552f7358SJed Brown   PetscInt numFields, foff, f;
7367552f7358SJed Brown 
7368552f7358SJed Brown   PetscFunctionBegin;
736908401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
73709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7371552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
73724acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7373552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
73744acb8e1eSToby Isaac     PetscInt        cind = 0, b;
73754acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7376552f7358SJed Brown 
73779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
73789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7379552f7358SJed Brown     if (!cfdof || setBC) {
738005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
738105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
738205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
738305586334SMatthew G. Knepley 
738405586334SMatthew G. Knepley         indices[ind] = off + foff + b;
738505586334SMatthew G. Knepley       }
7386552f7358SJed Brown     } else {
73879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
738805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
738905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
739005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
739105586334SMatthew G. Knepley 
73924acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
739305586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7394552f7358SJed Brown           ++cind;
7395552f7358SJed Brown         } else {
739636fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7397552f7358SJed Brown         }
7398552f7358SJed Brown       }
7399552f7358SJed Brown     }
740036fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7401552f7358SJed Brown     foffs[f] += fdof;
7402552f7358SJed Brown   }
74033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7404552f7358SJed Brown }
7405552f7358SJed Brown 
74067e29afd2SMatthew G. Knepley /*
74077e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
74087e29afd2SMatthew G. Knepley 
74097e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7410645102dcSJed Brown 
7411645102dcSJed Brown  Notes:
7412645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7413645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
74147e29afd2SMatthew G. Knepley */
7415d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7416d71ae5a4SJacob Faibussowitsch {
74177e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
74187e29afd2SMatthew G. Knepley 
74197e29afd2SMatthew G. Knepley   PetscFunctionBegin;
74209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
74217e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
74227e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
74237e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
74247e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
74257e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
74267e29afd2SMatthew G. Knepley 
74279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
74289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
74299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7430645102dcSJed Brown     if (!cfdof) {
743105586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
743205586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
743305586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
743405586334SMatthew G. Knepley 
743505586334SMatthew G. Knepley         indices[ind] = foff + b;
743605586334SMatthew G. Knepley       }
74377e29afd2SMatthew G. Knepley     } else {
74389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
743905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
744005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
744105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
744205586334SMatthew G. Knepley 
74437e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
744405586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
74457e29afd2SMatthew G. Knepley           ++cind;
74467e29afd2SMatthew G. Knepley         } else {
744705586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
74487e29afd2SMatthew G. Knepley         }
74497e29afd2SMatthew G. Knepley       }
74507e29afd2SMatthew G. Knepley     }
74517e29afd2SMatthew G. Knepley     foffs[f] += fdof;
74527e29afd2SMatthew G. Knepley   }
74533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74547e29afd2SMatthew G. Knepley }
74557e29afd2SMatthew G. Knepley 
7456*c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms)
7457*c789d87fSToby Isaac {
7458*c789d87fSToby Isaac   PetscInt numFields, sStart, sEnd, cStart, cEnd;
7459*c789d87fSToby Isaac 
7460*c789d87fSToby Isaac   PetscFunctionBegin;
7461*c789d87fSToby Isaac   PetscCall(PetscSectionGetNumFields(section, &numFields));
7462*c789d87fSToby Isaac   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
7463*c789d87fSToby Isaac   PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
7464*c789d87fSToby Isaac   for (PetscInt p = 0; p < nPoints; p++) {
7465*c789d87fSToby Isaac     PetscInt     b       = pnts[2 * p];
7466*c789d87fSToby Isaac     PetscInt     bSecDof = 0, bOff;
7467*c789d87fSToby Isaac     PetscInt     cSecDof = 0;
7468*c789d87fSToby Isaac     PetscSection indices_section;
7469*c789d87fSToby Isaac 
7470*c789d87fSToby Isaac     if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7471*c789d87fSToby Isaac     if (!bSecDof) continue;
7472*c789d87fSToby Isaac     if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof));
7473*c789d87fSToby Isaac     indices_section = cSecDof > 0 ? cSec : section;
7474*c789d87fSToby Isaac     if (numFields) {
7475*c789d87fSToby Isaac       PetscInt fStart[32], fEnd[32];
7476*c789d87fSToby Isaac 
7477*c789d87fSToby Isaac       fStart[0] = 0;
7478*c789d87fSToby Isaac       fEnd[0]   = 0;
7479*c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7480*c789d87fSToby Isaac         PetscInt fDof = 0;
7481*c789d87fSToby Isaac 
7482*c789d87fSToby Isaac         PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof));
7483*c789d87fSToby Isaac         fStart[f + 1] = fStart[f] + fDof;
7484*c789d87fSToby Isaac         fEnd[f + 1]   = fStart[f + 1];
7485*c789d87fSToby Isaac       }
7486*c789d87fSToby Isaac       PetscCall(PetscSectionGetOffset(indices_section, b, &bOff));
7487*c789d87fSToby Isaac       // only apply permutations on one side
7488*c789d87fSToby Isaac       PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices));
7489*c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7490*c789d87fSToby Isaac         for (PetscInt i = fStart[f]; i < fEnd[f]; i++) { indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); }
7491*c789d87fSToby Isaac       }
7492*c789d87fSToby Isaac     } else {
7493*c789d87fSToby Isaac       PetscInt bEnd = 0;
7494*c789d87fSToby Isaac 
7495*c789d87fSToby Isaac       PetscCall(PetscSectionGetOffset(indices_section, b, &bOff));
7496*c789d87fSToby Isaac       PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices));
7497*c789d87fSToby Isaac 
7498*c789d87fSToby Isaac       for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1);
7499*c789d87fSToby Isaac     }
7500*c789d87fSToby Isaac   }
7501*c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7502*c789d87fSToby Isaac }
7503*c789d87fSToby Isaac 
7504*c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsGetSubMatModification(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscInt offsets[], PetscScalar *outMat[])
7505d71ae5a4SJacob Faibussowitsch {
7506d3d1a6afSToby Isaac   Mat             cMat;
7507d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7508d3d1a6afSToby Isaac   IS              aIS;
7509d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7510a19ea1e9SMatthew G. Knepley   PetscInt        sStart = -1, sEnd = -1;
7511a19ea1e9SMatthew G. Knepley   PetscInt        cStart = -1, cEnd = -1;
7512d3d1a6afSToby Isaac   const PetscInt *anchors;
7513*c789d87fSToby Isaac   PetscInt        numFields, f, p;
7514d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7515*c789d87fSToby Isaac   PetscInt       *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices;
7516*c789d87fSToby Isaac   PetscInt        oldOffsets[32];
7517d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7518*c789d87fSToby Isaac   PetscInt        oldOffsetsCopy[32];
7519*c789d87fSToby Isaac   PetscInt        newOffsetsCopy[32];
7520*c789d87fSToby Isaac   PetscScalar    *modMat         = NULL;
7521d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7522d3d1a6afSToby Isaac 
7523d3d1a6afSToby Isaac   PetscFunctionBegin;
7524d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7525d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7527d3d1a6afSToby Isaac 
75289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7529d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7530d3d1a6afSToby Isaac   if (aSec) {
75319566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
7532*c789d87fSToby Isaac     PetscCall(PetscArrayzero(oldOffsets, 32));
75339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
75349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7535a19ea1e9SMatthew G. Knepley     PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
7536d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7537d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7538d3d1a6afSToby Isaac      * into the global matrix anyway) */
7539d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7540d3d1a6afSToby Isaac       PetscInt b    = points[p];
7541a19ea1e9SMatthew G. Knepley       PetscInt bDof = 0, bSecDof = 0;
7542d3d1a6afSToby Isaac 
7543a19ea1e9SMatthew G. Knepley       if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7544ad540459SPierre Jolivet       if (!bSecDof) continue;
7545*c789d87fSToby Isaac 
7546*c789d87fSToby Isaac       for (PetscInt f = 0; f < numFields; f++) {
7547*c789d87fSToby Isaac         PetscInt fDof = 0;
7548*c789d87fSToby Isaac 
7549*c789d87fSToby Isaac         PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7550*c789d87fSToby Isaac         oldOffsets[f + 1] += fDof;
7551*c789d87fSToby Isaac       }
755248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7553d3d1a6afSToby Isaac       if (bDof) {
7554d3d1a6afSToby Isaac         /* this point is constrained */
7555d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7556d3d1a6afSToby Isaac         PetscInt bOff, q;
7557d3d1a6afSToby Isaac 
75589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7559d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7560d3d1a6afSToby Isaac           PetscInt a    = anchors[bOff + q];
7561a19ea1e9SMatthew G. Knepley           PetscInt aDof = 0;
7562d3d1a6afSToby Isaac 
7563a19ea1e9SMatthew G. Knepley           if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof));
7564*c789d87fSToby Isaac           if (aDof) {
7565*c789d87fSToby Isaac             anyConstrained = PETSC_TRUE;
7566*c789d87fSToby Isaac             newNumPoints += 1;
7567*c789d87fSToby Isaac           }
7568d3d1a6afSToby Isaac           newNumIndices += aDof;
7569d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7570a19ea1e9SMatthew G. Knepley             PetscInt fDof = 0;
7571d3d1a6afSToby Isaac 
7572a19ea1e9SMatthew G. Knepley             if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7573d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7574d3d1a6afSToby Isaac           }
7575d3d1a6afSToby Isaac         }
75769371c9d4SSatish Balay       } else {
7577d3d1a6afSToby Isaac         /* this point is not constrained */
7578d3d1a6afSToby Isaac         newNumPoints++;
75794b2f2278SToby Isaac         newNumIndices += bSecDof;
7580d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7581d3d1a6afSToby Isaac           PetscInt fDof;
7582d3d1a6afSToby Isaac 
75839566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7584d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7585d3d1a6afSToby Isaac         }
7586d3d1a6afSToby Isaac       }
7587d3d1a6afSToby Isaac     }
7588d3d1a6afSToby Isaac   }
7589d3d1a6afSToby Isaac   if (!anyConstrained) {
759072b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
759172b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
759272b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
7593*c789d87fSToby Isaac     if (outMat) *outMat = NULL;
75949566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
75953ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7596d3d1a6afSToby Isaac   }
7597d3d1a6afSToby Isaac 
75986ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
75996ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
76006ecaa68aSToby Isaac 
7601f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7602*c789d87fSToby Isaac   for (f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f];
7603d3d1a6afSToby Isaac 
7604*c789d87fSToby Isaac   if (!outPoints && !outMat) {
76056ecaa68aSToby Isaac     if (offsets) {
7606ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
76076ecaa68aSToby Isaac     }
76089566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
76093ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
76106ecaa68aSToby Isaac   }
76116ecaa68aSToby Isaac 
76121dca8a05SBarry 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);
7613*c789d87fSToby Isaac   PetscCheck(!numFields || oldOffsets[numFields] == numIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, oldOffsets[numFields], numIndices);
7614d3d1a6afSToby Isaac 
76159566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7616a19ea1e9SMatthew G. Knepley   PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd));
7617d3d1a6afSToby Isaac 
7618*c789d87fSToby Isaac   /* output arrays */
7619*c789d87fSToby Isaac   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
7620*c789d87fSToby Isaac   PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints));
7621d3d1a6afSToby Isaac 
7622*c789d87fSToby Isaac   // get the new Points
7623*c789d87fSToby Isaac   for (PetscInt p = 0, newP = 0; p < numPoints; p++) {
7624d3d1a6afSToby Isaac     PetscInt b    = points[2 * p];
7625*c789d87fSToby Isaac     PetscInt bDof = 0, bSecDof = 0, bOff;
7626d3d1a6afSToby Isaac 
7627a19ea1e9SMatthew G. Knepley     if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7628*c789d87fSToby Isaac     if (!bSecDof) continue;
762948a46eb9SPierre Jolivet     if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7630d3d1a6afSToby Isaac     if (bDof) {
76319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7632*c789d87fSToby Isaac       for (PetscInt q = 0; q < bDof; q++) {
7633a19ea1e9SMatthew G. Knepley         PetscInt a = anchors[bOff + q], aDof = 0;
7634d3d1a6afSToby Isaac 
7635a19ea1e9SMatthew G. Knepley         if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof));
7636*c789d87fSToby Isaac         if (aDof) {
7637*c789d87fSToby Isaac           newPoints[2 * newP]     = a;
7638*c789d87fSToby Isaac           newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation
7639d3d1a6afSToby Isaac           newP++;
7640d3d1a6afSToby Isaac         }
7641d3d1a6afSToby Isaac       }
7642d3d1a6afSToby Isaac     } else {
7643d3d1a6afSToby Isaac       newPoints[2 * newP]     = b;
7644*c789d87fSToby Isaac       newPoints[2 * newP + 1] = points[2 * p + 1];
7645d3d1a6afSToby Isaac       newP++;
7646d3d1a6afSToby Isaac     }
7647d3d1a6afSToby Isaac   }
7648d3d1a6afSToby Isaac 
7649*c789d87fSToby Isaac   if (outMat) {
7650*c789d87fSToby Isaac     PetscScalar *tmpMat;
7651*c789d87fSToby Isaac     PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32));
7652*c789d87fSToby Isaac     PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32));
7653*c789d87fSToby Isaac 
7654*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices));
7655*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices));
7656*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices));
7657*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices));
7658*c789d87fSToby Isaac 
7659*c789d87fSToby Isaac     for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1;
7660*c789d87fSToby Isaac     for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1;
7661*c789d87fSToby Isaac 
7662*c789d87fSToby Isaac     PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms));
7663*c789d87fSToby Isaac     PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL));
7664*c789d87fSToby Isaac 
7665*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat));
7666*c789d87fSToby Isaac     PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat));
7667*c789d87fSToby Isaac     PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices));
7668*c789d87fSToby Isaac     // for each field, insert the anchor modification into modMat
7669*c789d87fSToby Isaac     for (PetscInt f = 0; f < PetscMax(1, numFields); f++) {
7670*c789d87fSToby Isaac       PetscInt fStart    = oldOffsets[f];
7671*c789d87fSToby Isaac       PetscInt fNewStart = newOffsets[f];
7672*c789d87fSToby Isaac       for (PetscInt p = 0, newP = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) {
7673*c789d87fSToby Isaac         PetscInt b    = points[2 * p];
7674*c789d87fSToby Isaac         PetscInt bDof = 0, bSecDof = 0, bOff;
7675*c789d87fSToby Isaac 
7676*c789d87fSToby Isaac         if (b >= sStart && b < sEnd) {
7677d3d1a6afSToby Isaac           if (numFields) {
7678*c789d87fSToby Isaac             PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof));
76799371c9d4SSatish Balay           } else {
7680*c789d87fSToby Isaac             PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7681d3d1a6afSToby Isaac           }
7682d3d1a6afSToby Isaac         }
7683*c789d87fSToby Isaac         if (!bSecDof) continue;
7684*c789d87fSToby Isaac         if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7685*c789d87fSToby Isaac         if (bDof) {
7686*c789d87fSToby Isaac           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7687*c789d87fSToby Isaac           for (PetscInt q = 0; q < bDof; q++, newP++) {
7688*c789d87fSToby Isaac             PetscInt a = anchors[bOff + q], aDof = 0;
7689d3d1a6afSToby Isaac 
7690*c789d87fSToby Isaac             if (a >= sStart && a < sEnd) {
7691d3d1a6afSToby Isaac               if (numFields) {
7692*c789d87fSToby Isaac                 PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
7693*c789d87fSToby Isaac               } else {
7694*c789d87fSToby Isaac                 PetscCall(PetscSectionGetDof(section, a, &aDof));
7695d3d1a6afSToby Isaac               }
7696d3d1a6afSToby Isaac             }
7697*c789d87fSToby Isaac             if (aDof) {
7698*c789d87fSToby Isaac               PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat));
7699*c789d87fSToby Isaac               for (PetscInt d = 0; d < bSecDof; d++) {
7700*c789d87fSToby Isaac                 for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e];
7701*c789d87fSToby Isaac               }
7702*c789d87fSToby Isaac             }
7703*c789d87fSToby Isaac             oNew += aDof;
7704*c789d87fSToby Isaac           }
77059371c9d4SSatish Balay         } else {
7706*c789d87fSToby Isaac           // Insert the identity matrix in this block
7707*c789d87fSToby Isaac           for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1;
7708*c789d87fSToby Isaac           oNew += bSecDof;
7709*c789d87fSToby Isaac           newP++;
7710d3d1a6afSToby Isaac         }
7711*c789d87fSToby Isaac         o += bSecDof;
7712d3d1a6afSToby Isaac       }
7713d3d1a6afSToby Isaac     }
7714d3d1a6afSToby Isaac 
7715*c789d87fSToby Isaac     *outMat = modMat;
77166ecaa68aSToby Isaac 
7717*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat));
7718*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices));
7719*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices));
7720*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices));
7721*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices));
7722d3d1a6afSToby Isaac   }
77239566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7724d3d1a6afSToby Isaac 
7725d3d1a6afSToby Isaac   /* output */
77266ecaa68aSToby Isaac   if (outPoints) {
7727d3d1a6afSToby Isaac     *outPoints = newPoints;
77289371c9d4SSatish Balay   } else {
77299566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
77306ecaa68aSToby Isaac   }
7731ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
77323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7733d3d1a6afSToby Isaac }
7734d3d1a6afSToby Isaac 
7735*c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsModifyMat_Internal(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt numRows, PetscInt numCols, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyRight, PetscBool multiplyLeft)
7736*c789d87fSToby Isaac {
7737*c789d87fSToby Isaac   PetscScalar *modMat        = NULL;
7738*c789d87fSToby Isaac   PetscInt     newNumIndices = -1;
77397cd05799SMatthew G. Knepley 
7740*c789d87fSToby Isaac   PetscFunctionBegin;
7741*c789d87fSToby Isaac   /* If M is the matrix represented by values, get the matrix C such that we will add M * C (or, if multiplyLeft, C^T * M * C) into the global matrix.
7742*c789d87fSToby Isaac      modMat is that matrix C */
7743*c789d87fSToby Isaac   PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL));
7744*c789d87fSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
7745*c789d87fSToby Isaac   if (modMat) {
7746*c789d87fSToby Isaac     const PetscScalar *newValues = values;
77477cd05799SMatthew G. Knepley 
7748*c789d87fSToby Isaac     if (multiplyRight) {
7749*c789d87fSToby Isaac       PetscScalar *newNewValues = NULL;
7750*c789d87fSToby Isaac       PetscBLASInt M            = newNumIndices;
7751*c789d87fSToby Isaac       PetscBLASInt N            = numRows;
7752*c789d87fSToby Isaac       PetscBLASInt K            = numIndices;
7753*c789d87fSToby Isaac       PetscScalar  a = 1.0, b = 0.0;
77547cd05799SMatthew G. Knepley 
7755*c789d87fSToby Isaac       PetscCheck(numCols == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of columns: %" PetscInt_FMT ", expected %" PetscInt_FMT, numCols, numIndices);
77567cd05799SMatthew G. Knepley 
7757*c789d87fSToby Isaac       PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues));
7758*c789d87fSToby Isaac       // row-major to column-major conversion, right multiplication becomes left multiplication
7759*c789d87fSToby Isaac       PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M));
776036fa2b79SJed Brown 
7761*c789d87fSToby Isaac       numCols   = newNumIndices;
7762*c789d87fSToby Isaac       newValues = newNewValues;
7763*c789d87fSToby Isaac     }
7764a1cb98faSBarry Smith 
7765*c789d87fSToby Isaac     if (multiplyLeft) {
7766*c789d87fSToby Isaac       PetscScalar *newNewValues = NULL;
7767*c789d87fSToby Isaac       PetscBLASInt M            = numCols;
7768*c789d87fSToby Isaac       PetscBLASInt N            = newNumIndices;
7769*c789d87fSToby Isaac       PetscBLASInt K            = numIndices;
7770*c789d87fSToby Isaac       PetscScalar  a = 1.0, b = 0.0;
77717cd05799SMatthew G. Knepley 
7772*c789d87fSToby Isaac       PetscCheck(numRows == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of rows: %" PetscInt_FMT ", expected %" PetscInt_FMT, numRows, numIndices);
7773*c789d87fSToby Isaac 
7774*c789d87fSToby Isaac       PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues));
7775*c789d87fSToby Isaac       // row-major to column-major conversion, left multiplication becomes right multiplication
7776*c789d87fSToby Isaac       PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M));
7777*c789d87fSToby Isaac       if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues));
7778*c789d87fSToby Isaac       newValues = newNewValues;
7779*c789d87fSToby Isaac     }
7780*c789d87fSToby Isaac     *outValues = (PetscScalar *)newValues;
7781*c789d87fSToby Isaac     PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat));
7782*c789d87fSToby Isaac   }
7783*c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7784*c789d87fSToby Isaac }
7785*c789d87fSToby Isaac 
7786*c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
7787*c789d87fSToby Isaac {
7788*c789d87fSToby Isaac   PetscFunctionBegin;
7789*c789d87fSToby Isaac   PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft));
7790*c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7791*c789d87fSToby Isaac }
7792*c789d87fSToby Isaac 
7793*c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize)
7794*c789d87fSToby Isaac {
7795*c789d87fSToby Isaac   /* Closure ordering */
7796*c789d87fSToby Isaac   PetscSection    clSection;
7797*c789d87fSToby Isaac   IS              clPoints;
7798*c789d87fSToby Isaac   const PetscInt *clp;
7799*c789d87fSToby Isaac   PetscInt       *points;
7800*c789d87fSToby Isaac   PetscInt        Ncl, Ni = 0;
7801*c789d87fSToby Isaac 
7802*c789d87fSToby Isaac   PetscFunctionBeginHot;
7803*c789d87fSToby Isaac   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7804*c789d87fSToby Isaac   for (PetscInt p = 0; p < Ncl * 2; p += 2) {
7805*c789d87fSToby Isaac     PetscInt dof;
7806*c789d87fSToby Isaac 
7807*c789d87fSToby Isaac     PetscCall(PetscSectionGetDof(section, points[p], &dof));
7808*c789d87fSToby Isaac     Ni += dof;
7809*c789d87fSToby Isaac   }
7810*c789d87fSToby Isaac   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7811*c789d87fSToby Isaac   *closureSize = Ni;
7812*c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
7813*c789d87fSToby Isaac }
7814*c789d87fSToby Isaac 
7815*c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndices_Internal(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numRows, PetscInt *numCols, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[], PetscBool multiplyRight, PetscBool multiplyLeft)
7816d71ae5a4SJacob Faibussowitsch {
781771f0bbf9SMatthew G. Knepley   /* Closure ordering */
78187773e69fSMatthew G. Knepley   PetscSection    clSection;
78197773e69fSMatthew G. Knepley   IS              clPoints;
782071f0bbf9SMatthew G. Knepley   const PetscInt *clp;
782171f0bbf9SMatthew G. Knepley   PetscInt       *points;
782271f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
782371f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
78244acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
782571f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
782671f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
782771f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
782871f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
782971f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
783071f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
783171f0bbf9SMatthew G. Knepley 
783271f0bbf9SMatthew G. Knepley   PetscInt *idx;
783371f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
783471f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
78357caea556SToby Isaac   PetscInt  idxStart, idxEnd;
7836*c789d87fSToby Isaac   PetscInt  nRows, nCols;
78377773e69fSMatthew G. Knepley 
783871f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
78397773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78407773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
784136fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7842*c789d87fSToby Isaac   PetscAssertPointer(numRows, 6);
7843*c789d87fSToby Isaac   PetscAssertPointer(numCols, 7);
7844*c789d87fSToby Isaac   if (indices) PetscAssertPointer(indices, 8);
7845*c789d87fSToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 9);
7846*c789d87fSToby Isaac   if (values) PetscAssertPointer(values, 10);
78479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
784863a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
78499566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
785071f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
785107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7852c459fbc1SJed Brown   if (useClPerm) {
7853c459fbc1SJed Brown     PetscInt depth, clsize;
78549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7855c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7856c459fbc1SJed Brown       PetscInt dof;
78579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7858c459fbc1SJed Brown       clsize += dof;
7859c459fbc1SJed Brown     }
78609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7861c459fbc1SJed Brown   }
786271f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
786371f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
78647773e69fSMatthew G. Knepley     PetscInt dof, fdof;
78657773e69fSMatthew G. Knepley 
78669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
78677773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
78689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
78697773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
78707773e69fSMatthew G. Knepley     }
787171f0bbf9SMatthew G. Knepley     Ni += dof;
78727773e69fSMatthew G. Knepley   }
7873*c789d87fSToby Isaac   if (*numRows == -1) *numRows = Ni;
7874*c789d87fSToby Isaac   if (*numCols == -1) *numCols = Ni;
7875*c789d87fSToby Isaac   nRows = *numRows;
7876*c789d87fSToby Isaac   nCols = *numCols;
78777773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
78781dca8a05SBarry 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);
787971f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
7880*c789d87fSToby Isaac   if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols);
7881*c789d87fSToby Isaac   if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows);
788271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
78839566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
78849566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
788571f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
788671f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
788771f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
78886ecaa68aSToby Isaac 
788971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
789071f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
789171f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
789271f0bbf9SMatthew G. Knepley 
78939566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
78949566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
789571f0bbf9SMatthew G. Knepley         if (flip) {
789671f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
789771f0bbf9SMatthew G. Knepley 
789871f0bbf9SMatthew G. Knepley           if (!valCopy) {
78999566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
790071f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
790171f0bbf9SMatthew G. Knepley             *values = valCopy;
790271f0bbf9SMatthew G. Knepley           }
790371f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
790471f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
790571f0bbf9SMatthew G. Knepley 
7906*c789d87fSToby Isaac             if (multiplyRight) {
7907*c789d87fSToby Isaac               for (k = 0; k < nRows; ++k) { valCopy[Ni * k + (foffset + i)] *= fval; }
7908*c789d87fSToby Isaac             }
7909*c789d87fSToby Isaac             if (multiplyLeft) {
7910*c789d87fSToby Isaac               for (k = 0; k < nCols; ++k) { valCopy[nCols * (foffset + i) + k] *= fval; }
79116ecaa68aSToby Isaac             }
79126ecaa68aSToby Isaac           }
791371f0bbf9SMatthew G. Knepley         }
791471f0bbf9SMatthew G. Knepley         foffset += fdof;
791571f0bbf9SMatthew G. Knepley       }
791671f0bbf9SMatthew G. Knepley     }
791771f0bbf9SMatthew G. Knepley   }
791871f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
7919*c789d87fSToby Isaac   PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft));
792071f0bbf9SMatthew G. Knepley   if (NclC) {
7921*c789d87fSToby Isaac     if (multiplyRight) { *numCols = nCols = NiC; }
7922*c789d87fSToby Isaac     if (multiplyLeft) { *numRows = nRows = NiC; }
79239566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
792471f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79259566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79269566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
792771f0bbf9SMatthew G. Knepley     }
792871f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
79299566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
79309566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
793171f0bbf9SMatthew G. Knepley     }
79329566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
793371f0bbf9SMatthew G. Knepley     Ncl    = NclC;
793471f0bbf9SMatthew G. Knepley     Ni     = NiC;
793571f0bbf9SMatthew G. Knepley     points = pointsC;
793671f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
793771f0bbf9SMatthew G. Knepley   }
793871f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
79399566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
79407caea556SToby Isaac   PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd));
794171f0bbf9SMatthew G. Knepley   if (Nf) {
794271f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
794371f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
794471f0bbf9SMatthew G. Knepley 
79459371c9d4SSatish Balay     if (outOffsets) {
79469371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
79479371c9d4SSatish Balay     }
79489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
794971f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
795071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
795171f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
795271f0bbf9SMatthew G. Knepley 
79539566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
79547773e69fSMatthew G. Knepley       }
79557773e69fSMatthew G. Knepley     } else {
795671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
795771f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
795871f0bbf9SMatthew G. Knepley 
79597caea556SToby Isaac         if (pnt < idxStart || pnt >= idxEnd) continue;
79609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
796171f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
796271f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
796371f0bbf9SMatthew G. Knepley          * global section. */
79649566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
796571f0bbf9SMatthew G. Knepley       }
796671f0bbf9SMatthew G. Knepley     }
796771f0bbf9SMatthew G. Knepley   } else {
796871f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
796971f0bbf9SMatthew G. Knepley 
797071f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
797171f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
79724acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
79734acb8e1eSToby Isaac 
79747caea556SToby Isaac       if (pnt < idxStart || pnt >= idxEnd) continue;
79759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
797671f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
797771f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
79789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
79797773e69fSMatthew G. Knepley     }
79807773e69fSMatthew G. Knepley   }
798171f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
798271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
79839566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
79849566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
79854acb8e1eSToby Isaac   }
798671f0bbf9SMatthew G. Knepley   if (NclC) {
79879566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
79887773e69fSMatthew G. Knepley   } else {
79899566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
79907773e69fSMatthew G. Knepley   }
799171f0bbf9SMatthew G. Knepley 
799271f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
79933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79947773e69fSMatthew G. Knepley }
79957773e69fSMatthew G. Knepley 
79967cd05799SMatthew G. Knepley /*@C
7997*c789d87fSToby Isaac   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
7998*c789d87fSToby Isaac 
7999*c789d87fSToby Isaac   Not collective
8000*c789d87fSToby Isaac 
8001*c789d87fSToby Isaac   Input Parameters:
8002*c789d87fSToby Isaac + dm         - The `DM`
8003*c789d87fSToby Isaac . section    - The `PetscSection` describing the points (a local section)
8004*c789d87fSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
8005*c789d87fSToby Isaac . point      - The point defining the closure
8006*c789d87fSToby Isaac - useClPerm  - Use the closure point permutation if available
8007*c789d87fSToby Isaac 
8008*c789d87fSToby Isaac   Output Parameters:
8009*c789d87fSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections
8010*c789d87fSToby Isaac . indices    - The dof indices
8011*c789d87fSToby Isaac . outOffsets - Array to write the field offsets into, or `NULL`
8012*c789d87fSToby Isaac - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
8013*c789d87fSToby Isaac 
8014*c789d87fSToby Isaac   Level: advanced
8015*c789d87fSToby Isaac 
8016*c789d87fSToby Isaac   Notes:
8017*c789d87fSToby Isaac   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
8018*c789d87fSToby Isaac 
8019*c789d87fSToby Isaac   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
8020*c789d87fSToby Isaac   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
8021*c789d87fSToby Isaac   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
8022*c789d87fSToby Isaac   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
8023*c789d87fSToby Isaac   indices (with the above semantics) are implied.
8024*c789d87fSToby Isaac 
8025*c789d87fSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
8026*c789d87fSToby Isaac           `PetscSection`, `DMGetGlobalSection()`
8027*c789d87fSToby Isaac @*/
8028*c789d87fSToby Isaac PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8029*c789d87fSToby Isaac {
8030*c789d87fSToby Isaac   PetscInt numRows = -1, numCols = -1;
8031*c789d87fSToby Isaac 
8032*c789d87fSToby Isaac   PetscFunctionBeginHot;
8033*c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE));
8034*c789d87fSToby Isaac   PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols);
8035*c789d87fSToby Isaac   *numIndices = numRows;
8036*c789d87fSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
8037*c789d87fSToby Isaac }
8038*c789d87fSToby Isaac 
8039*c789d87fSToby Isaac /*@C
804071f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
80417cd05799SMatthew G. Knepley 
80427cd05799SMatthew G. Knepley   Not collective
80437cd05799SMatthew G. Knepley 
80447cd05799SMatthew G. Knepley   Input Parameters:
8045a1cb98faSBarry Smith + dm         - The `DM`
8046a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
8047a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
804871f0bbf9SMatthew G. Knepley . point      - The point defining the closure
804971f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
805071f0bbf9SMatthew G. Knepley 
805171f0bbf9SMatthew G. Knepley   Output Parameters:
805271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
805371f0bbf9SMatthew G. Knepley . indices    - The dof indices
805420f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
805520f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
805671f0bbf9SMatthew G. Knepley 
8057a1cb98faSBarry Smith   Level: advanced
805871f0bbf9SMatthew G. Knepley 
8059a1cb98faSBarry Smith   Notes:
8060a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
8061a1cb98faSBarry Smith 
8062a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
806371f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
806471f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
806571f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
806671f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
80677cd05799SMatthew G. Knepley 
80681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
80697cd05799SMatthew G. Knepley @*/
8070d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
8071d71ae5a4SJacob Faibussowitsch {
80727773e69fSMatthew G. Knepley   PetscFunctionBegin;
80737773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80744f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
80759566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
80763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80777773e69fSMatthew G. Knepley }
80787773e69fSMatthew G. Knepley 
8079e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8080d71ae5a4SJacob Faibussowitsch {
8081552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
8082552f7358SJed Brown   PetscInt          *indices;
808371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
808471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
8085552f7358SJed Brown   PetscErrorCode     ierr;
8086552f7358SJed Brown 
8087552f7358SJed Brown   PetscFunctionBegin;
8088552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80899566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
80903dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
80919566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
80923dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
8093e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 5);
8094552f7358SJed Brown 
8095e8e188d2SZach Atkins   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values));
80960d644c17SKarl Rupp 
80979566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
8098d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
80994a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8100552f7358SJed Brown   if (ierr) {
8101552f7358SJed Brown     PetscMPIInt rank;
8102552f7358SJed Brown 
81039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81049566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81059566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
81069566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81079566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
8108c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
8109552f7358SJed Brown   }
81104a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
81114a1e0b3eSMatthew G. Knepley     PetscInt i;
81129566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
811363a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
81149566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
81154a1e0b3eSMatthew G. Knepley   }
811671f0bbf9SMatthew G. Knepley 
81179566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
81189566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
81193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81204acb8e1eSToby Isaac }
812171f0bbf9SMatthew G. Knepley 
81224a1e0b3eSMatthew G. Knepley /*@C
8123e8e188d2SZach Atkins   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
8124e8e188d2SZach Atkins 
8125e8e188d2SZach Atkins   Not collective
8126e8e188d2SZach Atkins 
8127e8e188d2SZach Atkins   Input Parameters:
8128e8e188d2SZach Atkins + dm            - The `DM`
8129e8e188d2SZach Atkins . section       - The section describing the layout in `v`, or `NULL` to use the default section
8130e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
8131e8e188d2SZach Atkins . A             - The matrix
8132e8e188d2SZach Atkins . point         - The point in the `DM`
8133e8e188d2SZach Atkins . values        - The array of values
8134e8e188d2SZach Atkins - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
8135e8e188d2SZach Atkins 
8136e8e188d2SZach Atkins   Level: intermediate
8137e8e188d2SZach Atkins 
8138e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
8139e8e188d2SZach Atkins @*/
8140e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8141e8e188d2SZach Atkins {
8142e8e188d2SZach Atkins   PetscFunctionBegin;
8143e8e188d2SZach Atkins   PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode));
8144e8e188d2SZach Atkins   PetscFunctionReturn(PETSC_SUCCESS);
8145e8e188d2SZach Atkins }
8146e8e188d2SZach Atkins 
8147e8e188d2SZach Atkins /*@C
814860225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
81494a1e0b3eSMatthew G. Knepley 
81504a1e0b3eSMatthew G. Knepley   Not collective
81514a1e0b3eSMatthew G. Knepley 
81524a1e0b3eSMatthew G. Knepley   Input Parameters:
8153a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
815420f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
8155e8e188d2SZach Atkins . useRowPerm       - The flag to use the closure permutation of the `dmRow` if available
815620f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
8157a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
815820f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
8159e8e188d2SZach Atkins . useColPerm       - The flag to use the closure permutation of the `dmCol` if available
816020f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
81614a1e0b3eSMatthew G. Knepley . A                - The matrix
8162a1cb98faSBarry Smith . point            - The point in the `DM`
81634a1e0b3eSMatthew G. Knepley . values           - The array of values
8164a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
81654a1e0b3eSMatthew G. Knepley 
81664a1e0b3eSMatthew G. Knepley   Level: intermediate
81674a1e0b3eSMatthew G. Knepley 
81681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
81694a1e0b3eSMatthew G. Knepley @*/
8170e8e188d2SZach 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)
8171d71ae5a4SJacob Faibussowitsch {
817271f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
817371f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
8174*c789d87fSToby Isaac   PetscInt           numIndicesRow = -1, numIndicesCol = -1;
81757caea556SToby Isaac   const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2;
8176*c789d87fSToby Isaac 
817771f0bbf9SMatthew G. Knepley   PetscErrorCode ierr;
817871f0bbf9SMatthew G. Knepley 
817971f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
818071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
81819566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
818271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
81839566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
818471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
8185e8e188d2SZach Atkins   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5);
81869566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
8187e8e188d2SZach Atkins   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6);
81889566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
8189e8e188d2SZach Atkins   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7);
8190e8e188d2SZach Atkins   PetscValidHeaderSpecific(A, MAT_CLASSID, 9);
819171f0bbf9SMatthew G. Knepley 
8192*c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow));
8193*c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol));
81947caea556SToby Isaac   valuesV1 = valuesV0;
8195*c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE));
81967caea556SToby Isaac   valuesV2 = valuesV1;
8197*c789d87fSToby Isaac   PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE));
819871f0bbf9SMatthew G. Knepley 
8199*c789d87fSToby Isaac   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2));
8200d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8201*c789d87fSToby Isaac   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode);
820271f0bbf9SMatthew G. Knepley   if (ierr) {
820371f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
820471f0bbf9SMatthew G. Knepley 
82059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
82069566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
82079566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
82087caea556SToby Isaac     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2));
82097caea556SToby Isaac     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1));
82107caea556SToby Isaac     if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2));
82117caea556SToby Isaac     if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1));
8212d3d1a6afSToby Isaac   }
821371f0bbf9SMatthew G. Knepley 
82147caea556SToby Isaac   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2));
82157caea556SToby Isaac   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1));
82167caea556SToby Isaac   if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2));
82177caea556SToby Isaac   if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1));
82183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8219552f7358SJed Brown }
8220552f7358SJed Brown 
8221d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
8222d71ae5a4SJacob Faibussowitsch {
8223de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
8224de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
8225de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
8226de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
822717c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8228de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
8229412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
82304ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
8231de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
8232de41b84cSMatthew G. Knepley 
8233de41b84cSMatthew G. Knepley   PetscFunctionBegin;
8234de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
8235de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
82369566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
8237de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
82389566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
8239de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
82409566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
8241de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
82429566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
8243de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
8244de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
82459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
824663a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
82479566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
82489566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
8249de41b84cSMatthew G. Knepley   /* Column indices */
82509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82514ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8252de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8253de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
82549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8255de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8256de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8257de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8258de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8259de41b84cSMatthew G. Knepley       ++q;
8260de41b84cSMatthew G. Knepley     }
8261de41b84cSMatthew G. Knepley   }
8262de41b84cSMatthew G. Knepley   numCPoints = q;
8263de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8264de41b84cSMatthew G. Knepley     PetscInt fdof;
8265de41b84cSMatthew G. Knepley 
82669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
82674ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8268de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8270de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8271de41b84cSMatthew G. Knepley     }
8272de41b84cSMatthew G. Knepley     numCIndices += dof;
8273de41b84cSMatthew G. Knepley   }
8274de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8275de41b84cSMatthew G. Knepley   /* Row indices */
82769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8277412e9a14SMatthew G. Knepley   {
8278012bc364SMatthew G. Knepley     DMPlexTransform tr;
8279012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8280012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8281012bc364SMatthew G. Knepley 
82829566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
82839566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
82849566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8285012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
82869566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8287412e9a14SMatthew G. Knepley   }
82889566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8289de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8290de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
82919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8292de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
82939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8294de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8295de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
82969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
82974ca5e9f5SMatthew G. Knepley         if (!dof) continue;
82989371c9d4SSatish Balay         for (s = 0; s < q; ++s)
82999371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
83004ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8301de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8302de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8303de41b84cSMatthew G. Knepley         ++q;
8304de41b84cSMatthew G. Knepley       }
8305de41b84cSMatthew G. Knepley     }
83069566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8307de41b84cSMatthew G. Knepley   }
8308de41b84cSMatthew G. Knepley   numFPoints = q;
8309de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8310de41b84cSMatthew G. Knepley     PetscInt fdof;
8311de41b84cSMatthew G. Knepley 
83129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
83134ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8314de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
83159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8316de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8317de41b84cSMatthew G. Knepley     }
8318de41b84cSMatthew G. Knepley     numFIndices += dof;
8319de41b84cSMatthew G. Knepley   }
8320de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8321de41b84cSMatthew G. Knepley 
83221dca8a05SBarry 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);
83231dca8a05SBarry 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);
83249566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83259566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8326de41b84cSMatthew G. Knepley   if (numFields) {
83274acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
83284acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
83294acb8e1eSToby Isaac 
83304acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
83319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
83329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8333de41b84cSMatthew G. Knepley     }
83344acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
83359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
83369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
83374acb8e1eSToby Isaac     }
83384acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
83399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
83409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
83414acb8e1eSToby Isaac     }
83424acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
83439566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
83449566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8345de41b84cSMatthew G. Knepley     }
8346de41b84cSMatthew G. Knepley   } else {
83474acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
83484acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
83494acb8e1eSToby Isaac 
83509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
83519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
83524acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
83534acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
83544acb8e1eSToby Isaac 
83559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
83569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8357de41b84cSMatthew G. Knepley     }
83584acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
83594acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
83604acb8e1eSToby Isaac 
83619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
83629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8363de41b84cSMatthew G. Knepley     }
83649566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
83659566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8366de41b84cSMatthew G. Knepley   }
83679566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83684acb8e1eSToby Isaac   /* TODO: flips */
8369d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8370de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8371de41b84cSMatthew G. Knepley   if (ierr) {
8372de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8373de41b84cSMatthew G. Knepley 
83749566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
83759566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
83769566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
83779566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83789566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8379de41b84cSMatthew G. Knepley   }
83809566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
83819566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
83829566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
83839566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
83843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8385de41b84cSMatthew G. Knepley }
8386de41b84cSMatthew G. Knepley 
8387d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8388d71ae5a4SJacob Faibussowitsch {
83897c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
83907c927364SMatthew G. Knepley   PetscInt       *cpoints      = NULL;
8391230af79eSStefano Zampini   PetscInt        foffsets[32] = {0}, coffsets[32] = {0};
839217c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8393412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
83947c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
83957c927364SMatthew G. Knepley 
83967c927364SMatthew G. Knepley   PetscFunctionBegin;
83977c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
83987c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
83999566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
84007c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
84019566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
84027c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
84039566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
84047c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
84059566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
84067c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
84079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
840863a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
84097c927364SMatthew G. Knepley   /* Column indices */
84109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
84117c927364SMatthew G. Knepley   maxFPoints = numCPoints;
84127c927364SMatthew G. Knepley   /* Compress out points not in the section */
84137c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
84149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
84157c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
84167c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
84177c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
84187c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
84197c927364SMatthew G. Knepley       ++q;
84207c927364SMatthew G. Knepley     }
84217c927364SMatthew G. Knepley   }
84227c927364SMatthew G. Knepley   numCPoints = q;
84237c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
84247c927364SMatthew G. Knepley     PetscInt fdof;
84257c927364SMatthew G. Knepley 
84269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
84277c927364SMatthew G. Knepley     if (!dof) continue;
84287c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
84299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
84307c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
84317c927364SMatthew G. Knepley     }
84327c927364SMatthew G. Knepley     numCIndices += dof;
84337c927364SMatthew G. Knepley   }
84347c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
84357c927364SMatthew G. Knepley   /* Row indices */
84369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8437412e9a14SMatthew G. Knepley   {
8438012bc364SMatthew G. Knepley     DMPlexTransform tr;
8439012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8440012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8441012bc364SMatthew G. Knepley 
84429566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
84439566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
84449566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8445012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
84469566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8447412e9a14SMatthew G. Knepley   }
84489566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
84497c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
84507c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
84519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
84527c927364SMatthew G. Knepley     /* Compress out points not in the section */
84539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
84547c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
84557c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
84569566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
84577c927364SMatthew G. Knepley         if (!dof) continue;
84589371c9d4SSatish Balay         for (s = 0; s < q; ++s)
84599371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
84607c927364SMatthew G. Knepley         if (s < q) continue;
84617c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
84627c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
84637c927364SMatthew G. Knepley         ++q;
84647c927364SMatthew G. Knepley       }
84657c927364SMatthew G. Knepley     }
84669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
84677c927364SMatthew G. Knepley   }
84687c927364SMatthew G. Knepley   numFPoints = q;
84697c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
84707c927364SMatthew G. Knepley     PetscInt fdof;
84717c927364SMatthew G. Knepley 
84729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
84737c927364SMatthew G. Knepley     if (!dof) continue;
84747c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
84759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
84767c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
84777c927364SMatthew G. Knepley     }
84787c927364SMatthew G. Knepley     numFIndices += dof;
84797c927364SMatthew G. Knepley   }
84807c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
84817c927364SMatthew G. Knepley 
84821dca8a05SBarry 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);
84831dca8a05SBarry 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);
84847c927364SMatthew G. Knepley   if (numFields) {
84854acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
84864acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
84874acb8e1eSToby Isaac 
84884acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
84899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
84909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
84917c927364SMatthew G. Knepley     }
84924acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
84939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
84949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
84954acb8e1eSToby Isaac     }
84964acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
84979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
84989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
84994acb8e1eSToby Isaac     }
85004acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
85019566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
85029566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
85037c927364SMatthew G. Knepley     }
85047c927364SMatthew G. Knepley   } else {
85054acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
85064acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
85074acb8e1eSToby Isaac 
85089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85104acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
85114acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
85124acb8e1eSToby Isaac 
85139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
85149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
85157c927364SMatthew G. Knepley     }
85164acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
85174acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
85184acb8e1eSToby Isaac 
85199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
85209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
85217c927364SMatthew G. Knepley     }
85229566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
85239566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
85247c927364SMatthew G. Knepley   }
85259566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
85269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
85273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85287c927364SMatthew G. Knepley }
85297c927364SMatthew G. Knepley 
85307cd05799SMatthew G. Knepley /*@C
85317cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
85327cd05799SMatthew G. Knepley 
85337cd05799SMatthew G. Knepley   Input Parameter:
8534a1cb98faSBarry Smith . dm - The `DMPLEX` object
85357cd05799SMatthew G. Knepley 
85367cd05799SMatthew G. Knepley   Output Parameter:
85377cd05799SMatthew G. Knepley . cellHeight - The height of a cell
85387cd05799SMatthew G. Knepley 
85397cd05799SMatthew G. Knepley   Level: developer
85407cd05799SMatthew G. Knepley 
85411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
85427cd05799SMatthew G. Knepley @*/
8543d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8544d71ae5a4SJacob Faibussowitsch {
8545552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8546552f7358SJed Brown 
8547552f7358SJed Brown   PetscFunctionBegin;
8548552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85494f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8550552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
85513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8552552f7358SJed Brown }
8553552f7358SJed Brown 
85547cd05799SMatthew G. Knepley /*@C
85557cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
85567cd05799SMatthew G. Knepley 
85577cd05799SMatthew G. Knepley   Input Parameters:
8558a1cb98faSBarry Smith + dm         - The `DMPLEX` object
85597cd05799SMatthew G. Knepley - cellHeight - The height of a cell
85607cd05799SMatthew G. Knepley 
85617cd05799SMatthew G. Knepley   Level: developer
85627cd05799SMatthew G. Knepley 
85631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
85647cd05799SMatthew G. Knepley @*/
8565d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8566d71ae5a4SJacob Faibussowitsch {
8567552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8568552f7358SJed Brown 
8569552f7358SJed Brown   PetscFunctionBegin;
8570552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8571552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
85723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8573552f7358SJed Brown }
8574552f7358SJed Brown 
8575e6139122SMatthew G. Knepley /*@
85762827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8577e6139122SMatthew G. Knepley 
85782827ebadSStefano Zampini   Input Parameters:
85792827ebadSStefano Zampini + dm - The `DMPLEX` object
85802827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8581e6139122SMatthew G. Knepley 
8582e6139122SMatthew G. Knepley   Output Parameters:
85832827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
85842827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8585e6139122SMatthew G. Knepley 
85862a9f31c0SMatthew G. Knepley   Level: advanced
8587e6139122SMatthew G. Knepley 
85882827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8589e6139122SMatthew G. Knepley @*/
85902827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8591d71ae5a4SJacob Faibussowitsch {
85922827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
85932827ebadSStefano Zampini   DMLabel  label;
85942827ebadSStefano Zampini   PetscInt pStart, pEnd;
8595e6139122SMatthew G. Knepley 
8596e6139122SMatthew G. Knepley   PetscFunctionBegin;
8597e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85982827ebadSStefano Zampini   if (start) {
85994f572ea9SToby Isaac     PetscAssertPointer(start, 3);
86002827ebadSStefano Zampini     *start = 0;
86012827ebadSStefano Zampini   }
86022827ebadSStefano Zampini   if (end) {
86034f572ea9SToby Isaac     PetscAssertPointer(end, 4);
86042827ebadSStefano Zampini     *end = 0;
86052827ebadSStefano Zampini   }
86062827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86072827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
86082827ebadSStefano Zampini   if (mesh->tr) {
86092827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
86102827ebadSStefano Zampini   } else {
86112827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
86122827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
86132827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
86142827ebadSStefano Zampini   }
86153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8616e6139122SMatthew G. Knepley }
8617e6139122SMatthew G. Knepley 
8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8619d71ae5a4SJacob Faibussowitsch {
8620552f7358SJed Brown   PetscSection section, globalSection;
8621552f7358SJed Brown   PetscInt    *numbers, p;
8622552f7358SJed Brown 
8623552f7358SJed Brown   PetscFunctionBegin;
8624d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
86259566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
86269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
862748a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
86289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
8629eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection));
86309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8631552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
86329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8633ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8634ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8635552f7358SJed Brown   }
86369566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8637ef48cebcSMatthew G. Knepley   if (globalSize) {
8638ef48cebcSMatthew G. Knepley     PetscLayout layout;
86399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
86409566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
86419566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8642ef48cebcSMatthew G. Knepley   }
86439566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
86449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
86453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8646552f7358SJed Brown }
8647552f7358SJed Brown 
8648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8649d71ae5a4SJacob Faibussowitsch {
8650412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8651552f7358SJed Brown 
8652552f7358SJed Brown   PetscFunctionBegin;
86539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
86549566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
86559566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
86569566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
86573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8658552f7358SJed Brown }
865981ed3555SMatthew G. Knepley 
86608dab3259SMatthew G. Knepley /*@
86617cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
86627cd05799SMatthew G. Knepley 
86637cd05799SMatthew G. Knepley   Input Parameter:
8664a1cb98faSBarry Smith . dm - The `DMPLEX` object
86657cd05799SMatthew G. Knepley 
86667cd05799SMatthew G. Knepley   Output Parameter:
86677cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
86687cd05799SMatthew G. Knepley 
86697cd05799SMatthew G. Knepley   Level: developer
86707cd05799SMatthew G. Knepley 
86711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
86727cd05799SMatthew G. Knepley @*/
8673d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8674d71ae5a4SJacob Faibussowitsch {
867581ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
867681ed3555SMatthew G. Knepley 
867781ed3555SMatthew G. Knepley   PetscFunctionBegin;
867881ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86799566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8680552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
86813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8682552f7358SJed Brown }
8683552f7358SJed Brown 
8684d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8685d71ae5a4SJacob Faibussowitsch {
8686412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
868781ed3555SMatthew G. Knepley 
868881ed3555SMatthew G. Knepley   PetscFunctionBegin;
868981ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
86919566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
86923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
869381ed3555SMatthew G. Knepley }
869481ed3555SMatthew G. Knepley 
86958dab3259SMatthew G. Knepley /*@
86966aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
86977cd05799SMatthew G. Knepley 
86987cd05799SMatthew G. Knepley   Input Parameter:
8699a1cb98faSBarry Smith . dm - The `DMPLEX` object
87007cd05799SMatthew G. Knepley 
87017cd05799SMatthew G. Knepley   Output Parameter:
87027cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
87037cd05799SMatthew G. Knepley 
87047cd05799SMatthew G. Knepley   Level: developer
87057cd05799SMatthew G. Knepley 
87061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87077cd05799SMatthew G. Knepley @*/
8708d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8709d71ae5a4SJacob Faibussowitsch {
8710552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8711552f7358SJed Brown 
8712552f7358SJed Brown   PetscFunctionBegin;
8713552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87149566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8715552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
87163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8717552f7358SJed Brown }
8718552f7358SJed Brown 
87198dab3259SMatthew G. Knepley /*@
8720966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8721966484cfSJed Brown 
872220f4b53cSBarry Smith   Collective
87237cd05799SMatthew G. Knepley 
87247cd05799SMatthew G. Knepley   Input Parameter:
8725a1cb98faSBarry Smith . dm - The `DMPLEX` object
87267cd05799SMatthew G. Knepley 
87277cd05799SMatthew G. Knepley   Output Parameter:
87287cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
87297cd05799SMatthew G. Knepley 
8730a1cb98faSBarry Smith   Level: developer
8731966484cfSJed Brown 
8732a1cb98faSBarry Smith   Notes:
8733a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8734966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8735966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8736966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8737966484cfSJed Brown 
8738966484cfSJed Brown   The partitioned mesh is
8739966484cfSJed Brown   ```
8740966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8741966484cfSJed Brown   ```
8742966484cfSJed Brown   and its global numbering is
8743966484cfSJed Brown   ```
8744966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8745966484cfSJed Brown   ```
8746966484cfSJed Brown   Then the global numbering is provided as
8747966484cfSJed Brown   ```
8748966484cfSJed Brown   [0] Number of indices in set 5
8749966484cfSJed Brown   [0] 0 0
8750966484cfSJed Brown   [0] 1 1
8751966484cfSJed Brown   [0] 2 3
8752966484cfSJed Brown   [0] 3 4
8753966484cfSJed Brown   [0] 4 -6
8754966484cfSJed Brown   [1] Number of indices in set 3
8755966484cfSJed Brown   [1] 0 2
8756966484cfSJed Brown   [1] 1 5
8757966484cfSJed Brown   [1] 2 6
8758966484cfSJed Brown   ```
8759966484cfSJed Brown 
87601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
87617cd05799SMatthew G. Knepley @*/
8762d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8763d71ae5a4SJacob Faibussowitsch {
8764ef48cebcSMatthew G. Knepley   IS        nums[4];
8765862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8766ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
87670c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8768ef48cebcSMatthew G. Knepley 
8769ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8770ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
87720c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
87739566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
87740c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8775862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8776862913ffSStefano Zampini     PetscInt end;
8777862913ffSStefano Zampini 
8778862913ffSStefano Zampini     depths[d] = depth - d;
87799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
87800c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8781862913ffSStefano Zampini   }
87820c15888dSMatthew G. Knepley   if (empty)
87830c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
87840c15888dSMatthew G. Knepley       depths[d] = -1;
87850c15888dSMatthew G. Knepley       starts[d] = -1;
87860c15888dSMatthew G. Knepley     }
87870c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
87881c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8789ad540459SPierre 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]);
87900c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8791ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8792ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8793ef48cebcSMatthew G. Knepley 
87949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
87959566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8796ef48cebcSMatthew G. Knepley     shift += gsize;
8797ef48cebcSMatthew G. Knepley   }
8798d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
87999566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
88003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8801ef48cebcSMatthew G. Knepley }
8802ef48cebcSMatthew G. Knepley 
880308a22f4bSMatthew G. Knepley /*@
880408a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
880508a22f4bSMatthew G. Knepley 
880608a22f4bSMatthew G. Knepley   Input Parameter:
8807a1cb98faSBarry Smith . dm - The `DMPLEX` object
880808a22f4bSMatthew G. Knepley 
880908a22f4bSMatthew G. Knepley   Output Parameter:
881008a22f4bSMatthew G. Knepley . ranks - The rank field
881108a22f4bSMatthew G. Knepley 
8812a1cb98faSBarry Smith   Options Database Key:
881320f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
881408a22f4bSMatthew G. Knepley 
881508a22f4bSMatthew G. Knepley   Level: intermediate
881608a22f4bSMatthew G. Knepley 
88171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
881808a22f4bSMatthew G. Knepley @*/
8819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8820d71ae5a4SJacob Faibussowitsch {
882108a22f4bSMatthew G. Knepley   DM             rdm;
882208a22f4bSMatthew G. Knepley   PetscFE        fe;
882308a22f4bSMatthew G. Knepley   PetscScalar   *r;
882408a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8825a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
882608a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8827a55f9a55SMatthew G. Knepley   PetscBool      simplex;
882808a22f4bSMatthew G. Knepley 
882908a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8830f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88314f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
88329566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
88339566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
88349566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
88359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
88369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8837a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
88389566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
88399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
88409566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
88419566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
88429566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
88439566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
88449566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
88459566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
884608a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
884708a22f4bSMatthew G. Knepley     PetscScalar *lr;
884808a22f4bSMatthew G. Knepley 
88499566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
885071f09efeSPierre Jolivet     if (lr) *lr = rank;
885108a22f4bSMatthew G. Knepley   }
88529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
88539566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
88543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
885508a22f4bSMatthew G. Knepley }
885608a22f4bSMatthew G. Knepley 
8857ca8062c8SMatthew G. Knepley /*@
8858acf3173eSStefano Zampini   DMPlexCreateLabelField - Create a field whose value is the label value for that point
885918e14f0cSMatthew G. Knepley 
886018e14f0cSMatthew G. Knepley   Input Parameters:
886120f4b53cSBarry Smith + dm    - The `DMPLEX`
886220f4b53cSBarry Smith - label - The `DMLabel`
886318e14f0cSMatthew G. Knepley 
886418e14f0cSMatthew G. Knepley   Output Parameter:
886518e14f0cSMatthew G. Knepley . val - The label value field
886618e14f0cSMatthew G. Knepley 
886720f4b53cSBarry Smith   Options Database Key:
886820f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
886918e14f0cSMatthew G. Knepley 
887018e14f0cSMatthew G. Knepley   Level: intermediate
887118e14f0cSMatthew G. Knepley 
88721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
887318e14f0cSMatthew G. Knepley @*/
8874d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8875d71ae5a4SJacob Faibussowitsch {
88761033741fSStefano Zampini   DM             rdm, plex;
8877acf3173eSStefano Zampini   Vec            lval;
8878acf3173eSStefano Zampini   PetscSection   section;
887918e14f0cSMatthew G. Knepley   PetscFE        fe;
888018e14f0cSMatthew G. Knepley   PetscScalar   *v;
8881acf3173eSStefano Zampini   PetscInt       dim, pStart, pEnd, p, cStart;
8882acf3173eSStefano Zampini   DMPolytopeType ct;
8883acf3173eSStefano Zampini   char           name[PETSC_MAX_PATH_LEN];
8884acf3173eSStefano Zampini   const char    *lname, *prefix;
888518e14f0cSMatthew G. Knepley 
888618e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
888718e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88884f572ea9SToby Isaac   PetscAssertPointer(label, 2);
88894f572ea9SToby Isaac   PetscAssertPointer(val, 3);
88909566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
8891acf3173eSStefano Zampini   PetscCall(DMConvert(rdm, DMPLEX, &plex));
8892acf3173eSStefano Zampini   PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL));
8893acf3173eSStefano Zampini   PetscCall(DMPlexGetCellType(plex, cStart, &ct));
8894acf3173eSStefano Zampini   PetscCall(DMDestroy(&plex));
88959566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
8896acf3173eSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
8897acf3173eSStefano Zampini   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
8898acf3173eSStefano Zampini   PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname));
8899acf3173eSStefano Zampini   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe));
8900acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)fe, ""));
89019566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
89029566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
89039566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
89049566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
8905acf3173eSStefano Zampini   PetscCall(DMCreateLocalVector(rdm, &lval));
8906acf3173eSStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)*val, lname));
8907acf3173eSStefano Zampini   PetscCall(DMGetLocalSection(rdm, &section));
8908acf3173eSStefano Zampini   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
8909acf3173eSStefano Zampini   PetscCall(VecGetArray(lval, &v));
8910acf3173eSStefano Zampini   for (p = pStart; p < pEnd; ++p) {
8911acf3173eSStefano Zampini     PetscInt cval, dof, off;
891218e14f0cSMatthew G. Knepley 
8913acf3173eSStefano Zampini     PetscCall(PetscSectionGetDof(section, p, &dof));
8914acf3173eSStefano Zampini     if (!dof) continue;
8915acf3173eSStefano Zampini     PetscCall(DMLabelGetValue(label, p, &cval));
8916acf3173eSStefano Zampini     PetscCall(PetscSectionGetOffset(section, p, &off));
8917acf3173eSStefano Zampini     for (PetscInt d = 0; d < dof; d++) v[off + d] = cval;
891818e14f0cSMatthew G. Knepley   }
8919acf3173eSStefano Zampini   PetscCall(VecRestoreArray(lval, &v));
8920acf3173eSStefano Zampini   PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val));
8921acf3173eSStefano Zampini   PetscCall(VecDestroy(&lval));
89229566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
89233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
892418e14f0cSMatthew G. Knepley }
892518e14f0cSMatthew G. Knepley 
892618e14f0cSMatthew G. Knepley /*@
8927ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8928ca8062c8SMatthew G. Knepley 
892969916449SMatthew G. Knepley   Input Parameter:
8930a1cb98faSBarry Smith . dm - The `DMPLEX` object
8931a1cb98faSBarry Smith 
8932a1cb98faSBarry Smith   Level: developer
8933ca8062c8SMatthew G. Knepley 
893495eb5ee5SVaclav Hapla   Notes:
893595eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
893695eb5ee5SVaclav Hapla 
893720f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8938ca8062c8SMatthew G. Knepley 
89391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8940ca8062c8SMatthew G. Knepley @*/
8941d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8942d71ae5a4SJacob Faibussowitsch {
8943ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8944ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8945ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
894657beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
894757beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8948ca8062c8SMatthew G. Knepley 
8949ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8950ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89519566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
89529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
89539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8954ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
89559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8956ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
89579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
89589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8959ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
896042e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
896142e66dfaSMatthew G. Knepley       PetscInt  d;
896242e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
89639371c9d4SSatish Balay         if (cone[c] == cone[d]) {
89649371c9d4SSatish Balay           dup = PETSC_TRUE;
89659371c9d4SSatish Balay           break;
89669371c9d4SSatish Balay         }
896742e66dfaSMatthew G. Knepley       }
89689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
89699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8970ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8971ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8972ca8062c8SMatthew G. Knepley       }
897342e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
897463a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
897548a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
89769566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
897763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
897848a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
89799566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
898063a3b9bcSJacob 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]);
8981f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8982ca8062c8SMatthew G. Knepley       }
898342e66dfaSMatthew G. Knepley     }
89849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
89859371c9d4SSatish Balay     if (p != pp) {
89869371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
89879371c9d4SSatish Balay       continue;
89889371c9d4SSatish Balay     }
89899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
89909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8991ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
89929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
89939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8994ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
89959566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
89969371c9d4SSatish Balay         if (cone[c] != pp) {
89979371c9d4SSatish Balay           c = 0;
89989371c9d4SSatish Balay           break;
89999371c9d4SSatish Balay         }
9000ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
9001ca8062c8SMatthew G. Knepley       }
9002ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
900363a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
900448a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
90059566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
900663a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
900748a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
90089566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
900963a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
9010ca8062c8SMatthew G. Knepley       }
9011ca8062c8SMatthew G. Knepley     }
9012ca8062c8SMatthew G. Knepley   }
901357beb4faSStefano Zampini   if (storagecheck) {
90149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
90159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
901663a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
901757beb4faSStefano Zampini   }
90183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9019ca8062c8SMatthew G. Knepley }
9020ca8062c8SMatthew G. Knepley 
9021412e9a14SMatthew G. Knepley /*
9022412e9a14SMatthew 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.
9023412e9a14SMatthew G. Knepley */
9024d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
9025d71ae5a4SJacob Faibussowitsch {
9026412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
9027412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
9028412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
9029412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
9030412e9a14SMatthew G. Knepley 
9031412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9032412e9a14SMatthew G. Knepley   *unsplit = 0;
9033412e9a14SMatthew G. Knepley   switch (ct) {
9034d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
9035d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
9036d71ae5a4SJacob Faibussowitsch     break;
9037412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
90389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
90399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9040412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
90419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
9042412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
9043412e9a14SMatthew G. Knepley     }
9044412e9a14SMatthew G. Knepley     break;
9045412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
9046412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
90479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
90489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
9049412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
90509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
90519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
9052412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
90539566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
9054412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
9055412e9a14SMatthew G. Knepley           PetscInt p;
90569371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
90579371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
9058412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
9059412e9a14SMatthew G. Knepley         }
9060412e9a14SMatthew G. Knepley       }
9061412e9a14SMatthew G. Knepley     }
9062412e9a14SMatthew G. Knepley     break;
9063d71ae5a4SJacob Faibussowitsch   default:
9064d71ae5a4SJacob Faibussowitsch     break;
9065412e9a14SMatthew G. Knepley   }
9066412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
90679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
9068412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
9069412e9a14SMatthew G. Knepley   }
90703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9071412e9a14SMatthew G. Knepley }
9072412e9a14SMatthew G. Knepley 
9073ca8062c8SMatthew G. Knepley /*@
9074ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
9075ca8062c8SMatthew G. Knepley 
9076ca8062c8SMatthew G. Knepley   Input Parameters:
9077a1cb98faSBarry Smith + dm         - The `DMPLEX` object
907858723a97SMatthew G. Knepley - cellHeight - Normally 0
9079ca8062c8SMatthew G. Knepley 
9080a1cb98faSBarry Smith   Level: developer
9081a1cb98faSBarry Smith 
908295eb5ee5SVaclav Hapla   Notes:
908395eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
908425c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
9085ca8062c8SMatthew G. Knepley 
908620f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
908795eb5ee5SVaclav Hapla 
90881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9089ca8062c8SMatthew G. Knepley @*/
9090d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
9091d71ae5a4SJacob Faibussowitsch {
9092412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
9093412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
9094412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
9095ca8062c8SMatthew G. Knepley 
9096ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
9097ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90989566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
90999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
91009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9101412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9102412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
9103412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
910458723a97SMatthew G. Knepley 
91059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
910663a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
9107412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
9108412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
91099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
911063a3b9bcSJacob 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));
9111412e9a14SMatthew G. Knepley     }
91129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
911358723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
911458723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
9115412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
911658723a97SMatthew G. Knepley     }
91179566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
9118412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
9119412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
9120412e9a14SMatthew G. Knepley       PetscInt unsplit;
912142363296SMatthew G. Knepley 
91229566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9123412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
912442363296SMatthew G. Knepley     }
912563a3b9bcSJacob 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));
912642363296SMatthew G. Knepley   }
91273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9128ca8062c8SMatthew G. Knepley }
91299bf0dad6SMatthew G. Knepley 
91309bf0dad6SMatthew G. Knepley /*@
91319bf0dad6SMatthew 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
91329bf0dad6SMatthew G. Knepley 
913320f4b53cSBarry Smith   Collective
9134899ea2b8SJacob Faibussowitsch 
91359bf0dad6SMatthew G. Knepley   Input Parameters:
9136a1cb98faSBarry Smith + dm         - The `DMPLEX` object
91379bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
91389bf0dad6SMatthew G. Knepley 
9139a1cb98faSBarry Smith   Level: developer
9140a1cb98faSBarry Smith 
914145da879fSVaclav Hapla   Notes:
914245da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
914345da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
914445da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
914545da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
91469bf0dad6SMatthew G. Knepley 
9147a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
914895eb5ee5SVaclav Hapla 
91491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
91509bf0dad6SMatthew G. Knepley @*/
9151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
9152d71ae5a4SJacob Faibussowitsch {
9153ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
9154899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
91559bf0dad6SMatthew G. Knepley 
91569bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
91579bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
91588f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
91593ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
91608f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
91613ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
91623ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9163899ea2b8SJacob Faibussowitsch   }
9164899ea2b8SJacob Faibussowitsch 
91659566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
91669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
91679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9168ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
91699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
91703554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
9171412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
9172412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
9173ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
9174412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
9175412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
91769bf0dad6SMatthew G. Knepley 
91779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
91789566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9179412e9a14SMatthew G. Knepley       if (unsplit) continue;
91809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
91819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
91829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
91839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
91849bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
91859bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
91869bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
91879bf0dad6SMatthew G. Knepley       }
91889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
918963a3b9bcSJacob 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);
91909bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
9191d4961f80SStefano Zampini         DMPolytopeType fct;
91929bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
91939bf0dad6SMatthew G. Knepley 
91949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
91959566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
91969bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
91979bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
91989bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
91999bf0dad6SMatthew G. Knepley         }
920063a3b9bcSJacob 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]);
92019bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
9202b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
9203b5a892a1SMatthew G. Knepley             PetscInt v1;
9204b5a892a1SMatthew G. Knepley 
92059566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
920663a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
92079566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
920863a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
92099566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
921063a3b9bcSJacob 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]);
9211b5a892a1SMatthew G. Knepley           }
92129bf0dad6SMatthew G. Knepley         }
92139566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
9214412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
92159bf0dad6SMatthew G. Knepley       }
92169566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
92179566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
92189bf0dad6SMatthew G. Knepley     }
92193554e41dSMatthew G. Knepley   }
92203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9221552f7358SJed Brown }
92223913d7c8SMatthew G. Knepley 
9223bb6a34a8SMatthew G. Knepley /*@
9224bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
9225bb6a34a8SMatthew G. Knepley 
9226bb6a34a8SMatthew G. Knepley   Input Parameter:
9227a1cb98faSBarry Smith . dm - The `DMPLEX` object
9228a1cb98faSBarry Smith 
9229a1cb98faSBarry Smith   Level: developer
9230bb6a34a8SMatthew G. Knepley 
923195eb5ee5SVaclav Hapla   Notes:
923295eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
923395eb5ee5SVaclav Hapla 
923420f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9235bb6a34a8SMatthew G. Knepley 
92361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
9237bb6a34a8SMatthew G. Knepley @*/
9238d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
9239d71ae5a4SJacob Faibussowitsch {
9240a2a9e04cSMatthew G. Knepley   Vec       coordinates;
9241bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
9242bb6a34a8SMatthew G. Knepley   PetscReal vol;
924351a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
9244bb6a34a8SMatthew G. Knepley 
9245bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
92469566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
92479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
92483ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
92499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
9250bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
92519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9252a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
92539566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
92543ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
9255412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
9256412e9a14SMatthew G. Knepley     DMPolytopeType ct;
9257412e9a14SMatthew G. Knepley     PetscInt       unsplit;
9258412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
9259412e9a14SMatthew G. Knepley 
92609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
9261412e9a14SMatthew G. Knepley     switch (ct) {
9262412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
9263412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9264d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9265d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9266d71ae5a4SJacob Faibussowitsch       break;
9267d71ae5a4SJacob Faibussowitsch     default:
9268d71ae5a4SJacob Faibussowitsch       break;
9269412e9a14SMatthew G. Knepley     }
9270412e9a14SMatthew G. Knepley     switch (ct) {
9271412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9272412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9273412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9274d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9275d71ae5a4SJacob Faibussowitsch       continue;
9276d71ae5a4SJacob Faibussowitsch     default:
9277d71ae5a4SJacob Faibussowitsch       break;
9278412e9a14SMatthew G. Knepley     }
92799566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9280412e9a14SMatthew G. Knepley     if (unsplit) continue;
92819566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
92821dca8a05SBarry 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);
928363a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
92846858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
92856858538eSMatthew G. Knepley     if (depth > 1) {
92869566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
92871dca8a05SBarry 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);
928863a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9289bb6a34a8SMatthew G. Knepley     }
9290bb6a34a8SMatthew G. Knepley   }
92913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9292bb6a34a8SMatthew G. Knepley }
9293bb6a34a8SMatthew G. Knepley 
929403da9461SVaclav Hapla /*@
929520f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
92967726db96SVaclav Hapla 
929720f4b53cSBarry Smith   Collective
929803da9461SVaclav Hapla 
929903da9461SVaclav Hapla   Input Parameters:
9300a1cb98faSBarry Smith + dm              - The `DMPLEX` object
930120f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9302a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9303a1cb98faSBarry Smith 
9304a1cb98faSBarry Smith   Level: developer
930503da9461SVaclav Hapla 
9306e83a0d2dSVaclav Hapla   Notes:
9307e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
930803da9461SVaclav Hapla 
9309a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
931095eb5ee5SVaclav Hapla 
9311baca6076SPierre Jolivet   Extra roots can come from periodic cuts, where additional points appear on the boundary
9312d7d32a9aSMatthew G. Knepley 
93131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
931403da9461SVaclav Hapla @*/
9315d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9316d71ae5a4SJacob Faibussowitsch {
93177726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
93187726db96SVaclav Hapla   const PetscInt    *locals;
93197726db96SVaclav Hapla   const PetscSFNode *remotes;
9320f0cfc026SVaclav Hapla   PetscBool          distributed;
93217726db96SVaclav Hapla   MPI_Comm           comm;
93227726db96SVaclav Hapla   PetscMPIInt        rank;
932303da9461SVaclav Hapla 
932403da9461SVaclav Hapla   PetscFunctionBegin;
932503da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93267726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
93277726db96SVaclav Hapla   else pointSF = dm->sf;
93287726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93297726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
93307726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
93317726db96SVaclav Hapla   {
93327726db96SVaclav Hapla     PetscMPIInt mpiFlag;
93337726db96SVaclav Hapla 
93347726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
93357726db96SVaclav 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);
93367726db96SVaclav Hapla   }
93377726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
93389566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
93397726db96SVaclav Hapla   if (!distributed) {
93407726db96SVaclav 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);
93413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
93428918e3e2SVaclav Hapla   }
93437726db96SVaclav 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);
93447726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
934503da9461SVaclav Hapla 
93467726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
93477726db96SVaclav Hapla   {
93487726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
93497726db96SVaclav Hapla 
93507726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
93517726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9352d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
93537726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
93547726db96SVaclav Hapla   }
93557726db96SVaclav Hapla 
93567726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
93577726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
93587726db96SVaclav 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);
93597726db96SVaclav Hapla   }
93607726db96SVaclav Hapla 
93617726db96SVaclav Hapla   /* Check there are no cells in interface */
93627726db96SVaclav Hapla   if (!overlap) {
93637726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
93647726db96SVaclav Hapla 
93659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
93669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9367f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
93687726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9369f5869d18SMatthew G. Knepley 
93707726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
93717726db96SVaclav Hapla     }
937203da9461SVaclav Hapla   }
9373ece87651SVaclav Hapla 
93747726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
93757726db96SVaclav Hapla   {
93767726db96SVaclav Hapla     const PetscInt *rootdegree;
93777726db96SVaclav Hapla 
93787726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
93797726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9380f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
93817726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9382f5869d18SMatthew G. Knepley       const PetscInt *cone;
9383f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9384f5869d18SMatthew G. Knepley 
93859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
93869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9387f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9388f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
93897726db96SVaclav Hapla           if (locals) {
93909566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
93917726db96SVaclav Hapla           } else {
93927726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
93937726db96SVaclav Hapla           }
939463a3b9bcSJacob 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]);
9395f5869d18SMatthew G. Knepley         }
9396f5869d18SMatthew G. Knepley       }
9397ece87651SVaclav Hapla     }
93987726db96SVaclav Hapla   }
93993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
940003da9461SVaclav Hapla }
940103da9461SVaclav Hapla 
94027f9d8d6cSVaclav Hapla /*@
940320f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
94047f9d8d6cSVaclav Hapla 
94057f9d8d6cSVaclav Hapla   Input Parameter:
9406a1cb98faSBarry Smith . dm - The `DMPLEX` object
9407a1cb98faSBarry Smith 
9408a1cb98faSBarry Smith   Level: developer
94097f9d8d6cSVaclav Hapla 
94107f9d8d6cSVaclav Hapla   Notes:
94117f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
94127f9d8d6cSVaclav Hapla 
941320f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
94147f9d8d6cSVaclav Hapla 
941520f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
94167f9d8d6cSVaclav Hapla 
94171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
94187f9d8d6cSVaclav Hapla @*/
9419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9420d71ae5a4SJacob Faibussowitsch {
94217f9d8d6cSVaclav Hapla   PetscInt cellHeight;
94227f9d8d6cSVaclav Hapla 
9423b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
94247f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94259566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
94269566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
94279566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
94289566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9429d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
94309566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
94313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9432b5a892a1SMatthew G. Knepley }
9433b5a892a1SMatthew G. Knepley 
94349371c9d4SSatish Balay typedef struct cell_stats {
9435068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9436068a5610SStefano Zampini   PetscInt  count;
9437068a5610SStefano Zampini } cell_stats_t;
9438068a5610SStefano Zampini 
9439d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9440d71ae5a4SJacob Faibussowitsch {
9441068a5610SStefano Zampini   PetscInt i, N = *len;
9442068a5610SStefano Zampini 
9443068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9444068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9445068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9446068a5610SStefano Zampini 
9447068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9448068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9449068a5610SStefano Zampini     B->sum += A->sum;
9450068a5610SStefano Zampini     B->squaresum += A->squaresum;
9451068a5610SStefano Zampini     B->count += A->count;
9452068a5610SStefano Zampini   }
9453068a5610SStefano Zampini }
9454068a5610SStefano Zampini 
9455068a5610SStefano Zampini /*@
945643fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9457068a5610SStefano Zampini 
945820f4b53cSBarry Smith   Collective
94598261a58bSMatthew G. Knepley 
9460068a5610SStefano Zampini   Input Parameters:
9461a1cb98faSBarry Smith + dm        - The `DMPLEX` object
946220f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9463a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9464a1cb98faSBarry Smith 
9465a1cb98faSBarry Smith   Level: developer
9466068a5610SStefano Zampini 
946795eb5ee5SVaclav Hapla   Notes:
946895eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
946995eb5ee5SVaclav Hapla 
9470a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9471068a5610SStefano Zampini 
94721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9473068a5610SStefano Zampini @*/
9474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9475d71ae5a4SJacob Faibussowitsch {
9476068a5610SStefano Zampini   DM           dmCoarse;
947743fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
947843fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
947943fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
948043fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9481412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
948243fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9483068a5610SStefano Zampini 
9484068a5610SStefano Zampini   PetscFunctionBegin;
9485068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9486068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9487068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9488068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9489068a5610SStefano Zampini   stats.count                 = 0;
9490068a5610SStefano Zampini 
94919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
94929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
94939566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
94949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
94959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
94969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9497412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9498068a5610SStefano Zampini     PetscInt  i;
9499068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9500068a5610SStefano Zampini 
95019566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
950263a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
950343fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9504068a5610SStefano Zampini       frobJ += J[i] * J[i];
9505068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9506068a5610SStefano Zampini     }
9507068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9508068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9509068a5610SStefano Zampini 
9510068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9511068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9512068a5610SStefano Zampini     stats.sum += cond;
9513068a5610SStefano Zampini     stats.squaresum += cond2;
9514068a5610SStefano Zampini     stats.count++;
95158261a58bSMatthew G. Knepley     if (output && cond > limit) {
951643fa8764SMatthew G. Knepley       PetscSection coordSection;
951743fa8764SMatthew G. Knepley       Vec          coordsLocal;
951843fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
951943fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
952043fa8764SMatthew G. Knepley 
95219566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
95229566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
95239566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
952463a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
952543fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
952663a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
952743fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
95289566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
95299566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
953043fa8764SMatthew G. Knepley         }
95319566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
953243fa8764SMatthew G. Knepley       }
95339566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
953443fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
953543fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
953643fa8764SMatthew G. Knepley 
953743fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
953843fa8764SMatthew G. Knepley           PetscReal len;
953943fa8764SMatthew G. Knepley 
95409566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
954163a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
954243fa8764SMatthew G. Knepley         }
954343fa8764SMatthew G. Knepley       }
95449566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
95459566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
954643fa8764SMatthew G. Knepley     }
9547068a5610SStefano Zampini   }
95489566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9549068a5610SStefano Zampini 
9550068a5610SStefano Zampini   if (size > 1) {
9551068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9552068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9553068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9554068a5610SStefano Zampini     MPI_Op       statReduce;
9555068a5610SStefano Zampini 
95569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
95579566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
95589566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
95599566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
95609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
95619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9562068a5610SStefano Zampini   } else {
95639566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9564068a5610SStefano Zampini   }
9565dd400576SPatrick Sanan   if (rank == 0) {
9566068a5610SStefano Zampini     count = globalStats.count;
9567068a5610SStefano Zampini     min   = globalStats.min;
9568068a5610SStefano Zampini     max   = globalStats.max;
9569068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9570068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9571068a5610SStefano Zampini   }
9572068a5610SStefano Zampini 
957348a46eb9SPierre 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));
95749566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9575068a5610SStefano Zampini 
95769566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9577068a5610SStefano Zampini   if (dmCoarse) {
9578068a5610SStefano Zampini     PetscBool isplex;
9579068a5610SStefano Zampini 
95809566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
95811baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9582068a5610SStefano Zampini   }
95833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9584068a5610SStefano Zampini }
9585068a5610SStefano Zampini 
9586f108dbd7SJacob Faibussowitsch /*@
9587f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9588f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9589f108dbd7SJacob Faibussowitsch 
959020f4b53cSBarry Smith   Collective
9591f108dbd7SJacob Faibussowitsch 
9592f108dbd7SJacob Faibussowitsch   Input Parameters:
9593a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9594a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9595f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9596f108dbd7SJacob Faibussowitsch 
9597f108dbd7SJacob Faibussowitsch   Output Parameters:
959820f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9599a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9600f108dbd7SJacob Faibussowitsch 
9601f108dbd7SJacob Faibussowitsch   Options Database Keys:
9602a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9603f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9604f108dbd7SJacob Faibussowitsch 
9605a1cb98faSBarry Smith   Level: intermediate
9606a1cb98faSBarry Smith 
9607f108dbd7SJacob Faibussowitsch   Notes:
9608a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9609f108dbd7SJacob Faibussowitsch 
9610a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9611f108dbd7SJacob Faibussowitsch 
9612f108dbd7SJacob 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
9613f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9614f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9615f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9616f108dbd7SJacob Faibussowitsch 
9617f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9618f108dbd7SJacob Faibussowitsch 
9619a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9620f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9621f108dbd7SJacob Faibussowitsch 
9622f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9623f108dbd7SJacob Faibussowitsch 
96241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9625f108dbd7SJacob Faibussowitsch @*/
9626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9627d71ae5a4SJacob Faibussowitsch {
96286ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
96296ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
96306ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9631f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
96326ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9633f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9634f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9635f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9636f108dbd7SJacob Faibussowitsch   IS                     glob;
9637f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9638f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9639f108dbd7SJacob Faibussowitsch 
9640f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9641f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9642ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
96434f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
96446bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
96459566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
96469566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
964763a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
96486ed19f2fSJacob Faibussowitsch   {
96496ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
96506ed19f2fSJacob Faibussowitsch 
96519566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9652f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9653f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9654f108dbd7SJacob Faibussowitsch 
96559566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
965698921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9657f108dbd7SJacob Faibussowitsch     }
96586ed19f2fSJacob Faibussowitsch   }
9659f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
96604f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
96619566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
96629566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
96639371c9d4SSatish Balay   } else {
96649371c9d4SSatish Balay     *OrthQualLabel = NULL;
96659371c9d4SSatish Balay   }
96669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
96679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
96689566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
96699566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
96709566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
96719566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
96729566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
96739566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
96749566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
96759566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
96769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
96779566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
96789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
96799566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
96809566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
96819566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
96829566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
96839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
96846ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
96856ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9686f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9687f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9688898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9689f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9690f108dbd7SJacob Faibussowitsch 
96916ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9692f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9693f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
96949566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
96959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9696f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
96979566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
96986ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
96996ed19f2fSJacob Faibussowitsch       PetscInt         i;
97006ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9701f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9702f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9703f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9704f108dbd7SJacob Faibussowitsch 
9705f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9706f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
97079566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9708f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
97096ed19f2fSJacob Faibussowitsch       {
97106ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
97116ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
97126ed19f2fSJacob Faibussowitsch 
97139566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
97149566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
97159566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
97166ed19f2fSJacob Faibussowitsch       }
9717f108dbd7SJacob Faibussowitsch 
9718f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9719f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9720f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9721f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9722f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9723addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9724addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9725addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9726f108dbd7SJacob Faibussowitsch       }
9727addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9728addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9729addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9730f108dbd7SJacob Faibussowitsch 
9731f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9732f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9733f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9734f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9735f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9736f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9737f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9738f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9739f108dbd7SJacob Faibussowitsch       }
9740ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9741ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9742f108dbd7SJacob Faibussowitsch     }
97439566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
97449566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9745f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
97466ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9747f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
97489566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9749f108dbd7SJacob Faibussowitsch     }
9750f108dbd7SJacob Faibussowitsch   }
97519566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
97529566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
97539566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
97549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
97559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
97569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9757f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
97589566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9759f108dbd7SJacob Faibussowitsch   }
97609566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
9761cd791dc2SBarry Smith   PetscCall(PetscOptionsRestoreViewer(&vwr));
97629566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
97633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9764f108dbd7SJacob Faibussowitsch }
9765f108dbd7SJacob Faibussowitsch 
9766d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
97671eb70e55SToby Isaac  * interpolator construction */
9768d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9769d71ae5a4SJacob Faibussowitsch {
97701eb70e55SToby Isaac   PetscSection section, newSection, gsection;
97711eb70e55SToby Isaac   PetscSF      sf;
97721eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
97731eb70e55SToby Isaac 
97741eb70e55SToby Isaac   PetscFunctionBegin;
97751eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97764f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
97779566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
97789566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9779712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
97801eb70e55SToby Isaac   if (!ghasConstraints) {
97819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
97821eb70e55SToby Isaac     *odm = dm;
97833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
97841eb70e55SToby Isaac   }
97859566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
97869566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
97879566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
97889566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
9789eb9d3e4dSMatthew G. Knepley   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection));
97909566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
97919566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
97923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97931eb70e55SToby Isaac }
97941eb70e55SToby Isaac 
9795d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9796d71ae5a4SJacob Faibussowitsch {
97971eb70e55SToby Isaac   DM        dmco, dmfo;
97981eb70e55SToby Isaac   Mat       interpo;
97991eb70e55SToby Isaac   Vec       rscale;
98001eb70e55SToby Isaac   Vec       cglobalo, clocal;
98011eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
98021eb70e55SToby Isaac   PetscBool regular;
98031eb70e55SToby Isaac 
98041eb70e55SToby Isaac   PetscFunctionBegin;
98059566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
98069566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
98079566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
98089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
98099566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
98109566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
98119566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
98129566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
98139566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
98149566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
98159566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
98169566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
98179566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
98189566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
98199566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
98209566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
98219566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
98229566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
98239566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
98249566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
98259566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
98269566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
98279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
98289566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
98291eb70e55SToby Isaac   *shift = fglobal;
98309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
98319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
98329566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
98339566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
98349566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
98359566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
98369566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
98379566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
98383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98391eb70e55SToby Isaac }
98401eb70e55SToby Isaac 
9841d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9842d71ae5a4SJacob Faibussowitsch {
98431eb70e55SToby Isaac   PetscObject shifto;
98441eb70e55SToby Isaac   Vec         shift;
98451eb70e55SToby Isaac 
98461eb70e55SToby Isaac   PetscFunctionBegin;
98471eb70e55SToby Isaac   if (!interp) {
98481eb70e55SToby Isaac     Vec rscale;
98491eb70e55SToby Isaac 
98509566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
98519566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
98521eb70e55SToby Isaac   } else {
98539566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
98541eb70e55SToby Isaac   }
98559566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
98561eb70e55SToby Isaac   if (!shifto) {
98579566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
98589566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
98591eb70e55SToby Isaac     shifto = (PetscObject)shift;
98609566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
98611eb70e55SToby Isaac   }
98621eb70e55SToby Isaac   shift = (Vec)shifto;
98639566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
98649566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
98659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
98663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98671eb70e55SToby Isaac }
98681eb70e55SToby Isaac 
9869bceba477SMatthew G. Knepley /* Pointwise interpolation
9870bceba477SMatthew G. Knepley      Just code FEM for now
9871bceba477SMatthew G. Knepley      u^f = I u^c
98724ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
98734ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
98744ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9875bceba477SMatthew G. Knepley */
9876d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9877d71ae5a4SJacob Faibussowitsch {
9878bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9879bceba477SMatthew G. Knepley   PetscInt     m, n;
9880a063dac3SMatthew G. Knepley   void        *ctx;
988168132eb9SMatthew G. Knepley   DM           cdm;
9882cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9883bceba477SMatthew G. Knepley 
9884bceba477SMatthew G. Knepley   PetscFunctionBegin;
98859566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
98869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
98879566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
98889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
988968132eb9SMatthew G. Knepley 
98909566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
98919566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
98929566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
98939566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
98949566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
989568132eb9SMatthew G. Knepley 
98969566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
98979566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
98989566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
98999566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
99009566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
99014db47ee9SStefano Zampini   if (scaling) {
99025d1c2e58SMatthew G. Knepley     /* Use naive scaling */
99039566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
99044db47ee9SStefano Zampini   }
99053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9906a063dac3SMatthew G. Knepley }
9907bceba477SMatthew G. Knepley 
9908d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9909d71ae5a4SJacob Faibussowitsch {
99106dbf9973SLawrence Mitchell   VecScatter ctx;
991190748bafSMatthew G. Knepley 
9912a063dac3SMatthew G. Knepley   PetscFunctionBegin;
99139566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
99149566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
99159566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
99163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9917bceba477SMatthew G. Knepley }
9918bceba477SMatthew G. Knepley 
9919d71ae5a4SJacob 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[])
9920d71ae5a4SJacob Faibussowitsch {
992100635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
992200635df3SMatthew G. Knepley   PetscInt       c;
992300635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
99243e9753d6SMatthew G. Knepley }
99253e9753d6SMatthew G. Knepley 
9926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9927d71ae5a4SJacob Faibussowitsch {
9928b4937a87SMatthew G. Knepley   DM           dmc;
9929b4937a87SMatthew G. Knepley   PetscDS      ds;
9930b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9931b4937a87SMatthew G. Knepley   IS           cellIS;
9932b4937a87SMatthew G. Knepley   PetscFormKey key;
9933b4937a87SMatthew G. Knepley   PetscInt     depth;
9934b4937a87SMatthew G. Knepley 
9935b4937a87SMatthew G. Knepley   PetscFunctionBegin;
99369566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
99379566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
99389566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
99399566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
99409566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
99419566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
99429566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
99439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
99449566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
99459566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
99469566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9947b4937a87SMatthew G. Knepley   key.label = NULL;
9948b4937a87SMatthew G. Knepley   key.value = 0;
9949b4937a87SMatthew G. Knepley   key.field = 0;
9950b4937a87SMatthew G. Knepley   key.part  = 0;
99519566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
99529566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
99539566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
99549566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
99559566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
99569566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
99579566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
99589566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
99593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9960b4937a87SMatthew G. Knepley }
9961b4937a87SMatthew G. Knepley 
9962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9963d71ae5a4SJacob Faibussowitsch {
9964bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9965bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9966bd041c0cSMatthew G. Knepley   void        *ctx;
9967bd041c0cSMatthew G. Knepley   DM           cdm;
9968bd041c0cSMatthew G. Knepley   PetscBool    regular;
9969bd041c0cSMatthew G. Knepley 
9970bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
99713e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
99723e9753d6SMatthew G. Knepley     DM            dmc;
99733e9753d6SMatthew G. Knepley     PetscDS       ds;
9974b4937a87SMatthew G. Knepley     PetscWeakForm wf;
99753e9753d6SMatthew G. Knepley     Vec           u;
99763e9753d6SMatthew G. Knepley     IS            cellIS;
997706ad1575SMatthew G. Knepley     PetscFormKey  key;
99783e9753d6SMatthew G. Knepley     PetscInt      depth;
99793e9753d6SMatthew G. Knepley 
99809566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
99819566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
99829566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
99839566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
99849566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
99859566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
99869566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
99878d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
99889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
99899566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
99909566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
99916528b96dSMatthew G. Knepley     key.label = NULL;
99926528b96dSMatthew G. Knepley     key.value = 0;
99936528b96dSMatthew G. Knepley     key.field = 0;
999406ad1575SMatthew G. Knepley     key.part  = 0;
99959566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
99969566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
99978d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
99989566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
99993e9753d6SMatthew G. Knepley   } else {
100009566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
100019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
100029566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
100039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
10004bd041c0cSMatthew G. Knepley 
100059566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
100069566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
100079566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
100089566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
10009bd041c0cSMatthew G. Knepley 
100109566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
100119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
100129566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
100139566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
100143e9753d6SMatthew G. Knepley   }
100159566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
100163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10017bd041c0cSMatthew G. Knepley }
10018bd041c0cSMatthew G. Knepley 
100190aef6b92SMatthew G. Knepley /*@
100200aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100210aef6b92SMatthew G. Knepley 
100220aef6b92SMatthew G. Knepley   Input Parameter:
10023a1cb98faSBarry Smith . dm - The `DMPLEX` object
100240aef6b92SMatthew G. Knepley 
100250aef6b92SMatthew G. Knepley   Output Parameter:
100260aef6b92SMatthew G. Knepley . regular - The flag
100270aef6b92SMatthew G. Knepley 
100280aef6b92SMatthew G. Knepley   Level: intermediate
100290aef6b92SMatthew G. Knepley 
100301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
100310aef6b92SMatthew G. Knepley @*/
10032d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
10033d71ae5a4SJacob Faibussowitsch {
100340aef6b92SMatthew G. Knepley   PetscFunctionBegin;
100350aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100364f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
100370aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
100383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100390aef6b92SMatthew G. Knepley }
100400aef6b92SMatthew G. Knepley 
100410aef6b92SMatthew G. Knepley /*@
100420aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
100430aef6b92SMatthew G. Knepley 
100440aef6b92SMatthew G. Knepley   Input Parameters:
10045a1cb98faSBarry Smith + dm      - The `DMPLEX` object
100460aef6b92SMatthew G. Knepley - regular - The flag
100470aef6b92SMatthew G. Knepley 
100480aef6b92SMatthew G. Knepley   Level: intermediate
100490aef6b92SMatthew G. Knepley 
100501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
100510aef6b92SMatthew G. Knepley @*/
10052d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
10053d71ae5a4SJacob Faibussowitsch {
100540aef6b92SMatthew G. Knepley   PetscFunctionBegin;
100550aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100560aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
100573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100580aef6b92SMatthew G. Knepley }
100590aef6b92SMatthew G. Knepley 
10060a68b90caSToby Isaac /*@
10061f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
10062a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
10063a68b90caSToby Isaac 
10064a1cb98faSBarry Smith   Not Collective
10065a68b90caSToby Isaac 
10066f899ff85SJose E. Roman   Input Parameter:
10067a1cb98faSBarry Smith . dm - The `DMPLEX` object
10068a68b90caSToby Isaac 
10069a68b90caSToby Isaac   Output Parameters:
1007020f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
1007120f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
10072a68b90caSToby Isaac 
10073a68b90caSToby Isaac   Level: intermediate
10074a68b90caSToby Isaac 
100751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
10076a68b90caSToby Isaac @*/
10077d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
10078d71ae5a4SJacob Faibussowitsch {
10079a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
10080a68b90caSToby Isaac 
10081a68b90caSToby Isaac   PetscFunctionBegin;
10082a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100839566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
10084a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
10085a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
100863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10087a68b90caSToby Isaac }
10088a68b90caSToby Isaac 
10089a68b90caSToby Isaac /*@
10090a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
10091a68b90caSToby Isaac 
1009220f4b53cSBarry Smith   Collective
10093a68b90caSToby Isaac 
10094a68b90caSToby Isaac   Input Parameters:
10095a1cb98faSBarry Smith + dm            - The `DMPLEX` object
10096a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
10097a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10098a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
10099a68b90caSToby Isaac 
10100a68b90caSToby Isaac   Level: intermediate
10101a68b90caSToby Isaac 
10102a1cb98faSBarry Smith   Notes:
10103a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
10104a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
10105a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
10106a4e35b19SJacob Faibussowitsch 
10107a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
10108a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
10109a1cb98faSBarry Smith 
1011020f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
10111a1cb98faSBarry Smith 
101121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
10113a68b90caSToby Isaac @*/
10114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
10115d71ae5a4SJacob Faibussowitsch {
10116a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
10117e228b242SToby Isaac   PetscMPIInt result;
10118a68b90caSToby Isaac 
10119a68b90caSToby Isaac   PetscFunctionBegin;
10120a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10121e228b242SToby Isaac   if (anchorSection) {
10122e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
101239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
101241dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
10125e228b242SToby Isaac   }
10126e228b242SToby Isaac   if (anchorIS) {
10127e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
101289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
101291dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
10130e228b242SToby Isaac   }
10131a68b90caSToby Isaac 
101329566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
101339566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
10134a68b90caSToby Isaac   plex->anchorSection = anchorSection;
10135a68b90caSToby Isaac 
101369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
101379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
10138a68b90caSToby Isaac   plex->anchorIS = anchorIS;
10139a68b90caSToby Isaac 
10140cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
10141a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
10142a68b90caSToby Isaac     const PetscInt *anchors;
10143a68b90caSToby Isaac 
101449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
101459566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
101469566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
10147a68b90caSToby Isaac     for (a = 0; a < size; a++) {
10148a68b90caSToby Isaac       PetscInt p;
10149a68b90caSToby Isaac 
10150a68b90caSToby Isaac       p = anchors[a];
10151a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
10152a68b90caSToby Isaac         PetscInt dof;
10153a68b90caSToby Isaac 
101549566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10155a68b90caSToby Isaac         if (dof) {
101569566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
1015763a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
10158a68b90caSToby Isaac         }
10159a68b90caSToby Isaac       }
10160a68b90caSToby Isaac     }
101619566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
10162a68b90caSToby Isaac   }
10163f7c74593SToby Isaac   /* reset the generic constraints */
101649566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
101653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10166a68b90caSToby Isaac }
10167a68b90caSToby Isaac 
10168d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
10169d71ae5a4SJacob Faibussowitsch {
10170f7c74593SToby Isaac   PetscSection anchorSection;
101716995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
10172a68b90caSToby Isaac 
10173a68b90caSToby Isaac   PetscFunctionBegin;
10174a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
101759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
101769566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
101779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
101786995de1eSToby Isaac   if (numFields) {
10179719ab38cSToby Isaac     PetscInt f;
101809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
10181719ab38cSToby Isaac 
10182719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
10183719ab38cSToby Isaac       PetscInt numComp;
10184719ab38cSToby Isaac 
101859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
101869566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
10187719ab38cSToby Isaac     }
101886995de1eSToby Isaac   }
101899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
101909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
101916995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
101926995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
101936995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
101949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
10195a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
101969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
10197a68b90caSToby Isaac     if (dof) {
101989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
101999566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
10200a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
102019566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
102029566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
10203a68b90caSToby Isaac       }
10204a68b90caSToby Isaac     }
10205a68b90caSToby Isaac   }
102069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
102079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
102083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10209a68b90caSToby Isaac }
10210a68b90caSToby Isaac 
10211d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
10212d71ae5a4SJacob Faibussowitsch {
10213f7c74593SToby Isaac   PetscSection    aSec;
10214ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
102150ac89760SToby Isaac   const PetscInt *anchors;
102160ac89760SToby Isaac   PetscInt        numFields, f;
1021766ad2231SToby Isaac   IS              aIS;
10218e19f7ee6SMark Adams   MatType         mtype;
10219e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
102200ac89760SToby Isaac 
102210ac89760SToby Isaac   PetscFunctionBegin;
102220ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
102239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
102249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
102259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
102269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
102279566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
102289566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
102299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
102309566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
10231e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
10232e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
10233e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
102349566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
102359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
102369566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
102376995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
102389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
102399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
102409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
102410ac89760SToby Isaac   i[0] = 0;
102429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
102430ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
10244f19733c5SToby Isaac     PetscInt rDof, rOff, r;
10245f19733c5SToby Isaac 
102469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
10247f19733c5SToby Isaac     if (!rDof) continue;
102489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102490ac89760SToby Isaac     if (numFields) {
102500ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
102510ac89760SToby Isaac         annz = 0;
10252f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
10253f19733c5SToby Isaac           a = anchors[rOff + r];
10254ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
102559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
102560ac89760SToby Isaac           annz += aDof;
102570ac89760SToby Isaac         }
102589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
102599566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
10260ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
102610ac89760SToby Isaac       }
102622f7452b8SBarry Smith     } else {
102630ac89760SToby Isaac       annz = 0;
102649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102650ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10266ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10267ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
102689566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
102690ac89760SToby Isaac         annz += aDof;
102700ac89760SToby Isaac       }
102719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
102729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10273ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
102740ac89760SToby Isaac     }
102750ac89760SToby Isaac   }
102760ac89760SToby Isaac   nnz = i[m];
102779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
102780ac89760SToby Isaac   offset = 0;
102790ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
102800ac89760SToby Isaac     if (numFields) {
102810ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
102829566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
102830ac89760SToby Isaac         for (q = 0; q < dof; q++) {
102840ac89760SToby Isaac           PetscInt rDof, rOff, r;
102859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
102869566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
102870ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
102880ac89760SToby Isaac             PetscInt s;
102890ac89760SToby Isaac 
102900ac89760SToby Isaac             a = anchors[rOff + r];
10291ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
102929566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
102939566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10294ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
102950ac89760SToby Isaac           }
102960ac89760SToby Isaac         }
102970ac89760SToby Isaac       }
102982f7452b8SBarry Smith     } else {
102999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
103000ac89760SToby Isaac       for (q = 0; q < dof; q++) {
103010ac89760SToby Isaac         PetscInt rDof, rOff, r;
103029566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
103039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
103040ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
103050ac89760SToby Isaac           PetscInt s;
103060ac89760SToby Isaac 
103070ac89760SToby Isaac           a = anchors[rOff + r];
10308ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
103099566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
103109566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10311ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
103120ac89760SToby Isaac         }
103130ac89760SToby Isaac       }
103140ac89760SToby Isaac     }
103150ac89760SToby Isaac   }
103169566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
103179566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
103189566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
103199566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
103203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103210ac89760SToby Isaac }
103220ac89760SToby Isaac 
10323d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10324d71ae5a4SJacob Faibussowitsch {
10325f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10326f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1032766ad2231SToby Isaac   Mat          cMat;
1032866ad2231SToby Isaac 
1032966ad2231SToby Isaac   PetscFunctionBegin;
1033066ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
103319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1033266ad2231SToby Isaac   if (anchorSection) {
1033344a7f3ddSMatthew G. Knepley     PetscInt Nf;
10334e228b242SToby Isaac 
103359566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
103369566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
103379566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
103389566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
103399566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
103409566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
103419566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
103429566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1034366ad2231SToby Isaac   }
103443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1034566ad2231SToby Isaac }
10346a93c429eSMatthew G. Knepley 
10347d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10348d71ae5a4SJacob Faibussowitsch {
10349a93c429eSMatthew G. Knepley   IS           subis;
10350a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10351a93c429eSMatthew G. Knepley 
10352a93c429eSMatthew G. Knepley   PetscFunctionBegin;
103539566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1035428b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1035528b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10356a93c429eSMatthew G. Knepley   /* Create subdomain */
103579566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10358a93c429eSMatthew G. Knepley   /* Create submodel */
103599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
103609566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
103619566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
103629566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
103639566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10364a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10365a93c429eSMatthew G. Knepley   if (is) {
10366a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10367a93c429eSMatthew G. Knepley     IS              spIS;
10368a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10369a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10370a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10371a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10372a93c429eSMatthew G. Knepley 
103739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
103749566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
103759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
103769566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
103779566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
103789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10379a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10380a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10381a93c429eSMatthew G. Knepley 
103829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10383a93c429eSMatthew G. Knepley       if (gdof > 0) {
10384a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10385a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10386a93c429eSMatthew G. Knepley 
103879566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
103889566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10389a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10390a93c429eSMatthew G. Knepley         }
10391a93c429eSMatthew G. Knepley         subSize += pSubSize;
10392a93c429eSMatthew G. Knepley         if (pSubSize) {
10393a93c429eSMatthew G. Knepley           if (bs < 0) {
10394a93c429eSMatthew G. Knepley             bs = pSubSize;
10395a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10396a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10397a93c429eSMatthew G. Knepley             bs = 1;
10398a93c429eSMatthew G. Knepley           }
10399a93c429eSMatthew G. Knepley         }
10400a93c429eSMatthew G. Knepley       }
10401a93c429eSMatthew G. Knepley     }
10402a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
104039371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
104049371c9d4SSatish Balay     bsLocal[1] = bs;
104059566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
104069371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
104079371c9d4SSatish Balay       bs = 1;
104089371c9d4SSatish Balay     } else {
104099371c9d4SSatish Balay       bs = bsMinMax[0];
104109371c9d4SSatish Balay     }
104119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10412a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10413a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10414a93c429eSMatthew G. Knepley 
104159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10416a93c429eSMatthew G. Knepley       if (gdof > 0) {
10417a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10418a93c429eSMatthew G. Knepley 
104199566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10420a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10421a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10422a93c429eSMatthew G. Knepley 
10423a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10424a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
104259566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
104269566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10427a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10428a93c429eSMatthew G. Knepley           }
104299566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
104309566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10431ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10432a93c429eSMatthew G. Knepley         }
10433a93c429eSMatthew G. Knepley       }
10434a93c429eSMatthew G. Knepley     }
104359566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
104369566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10437a93c429eSMatthew G. Knepley     if (bs > 1) {
10438a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10439a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10440a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10441a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
104429371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
104439371c9d4SSatish Balay             set = 0;
104449371c9d4SSatish Balay             break;
104459371c9d4SSatish Balay           }
10446a93c429eSMatthew G. Knepley         }
10447a93c429eSMatthew G. Knepley       }
104489566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10449a93c429eSMatthew G. Knepley     }
10450a93c429eSMatthew G. Knepley     /* Attach nullspace */
10451a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10452a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10453a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10454a93c429eSMatthew G. Knepley     }
10455a93c429eSMatthew G. Knepley     if (f < Nf) {
10456a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
104579566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
104586823f3c5SBlaise Bourdin 
104599566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
104609566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10461a93c429eSMatthew G. Knepley     }
10462a93c429eSMatthew G. Knepley   }
104633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10464a93c429eSMatthew G. Knepley }
10465c0f0dcc3SMatthew G. Knepley 
10466c0f0dcc3SMatthew G. Knepley /*@
10467c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10468c0f0dcc3SMatthew G. Knepley 
10469a1cb98faSBarry Smith   Input Parameters:
10470a1cb98faSBarry Smith + dm    - The `DM`
10471a1cb98faSBarry Smith - dummy - unused argument
10472a1cb98faSBarry Smith 
10473a1cb98faSBarry Smith   Options Database Key:
10474a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10475c0f0dcc3SMatthew G. Knepley 
10476c0f0dcc3SMatthew G. Knepley   Level: developer
10477c0f0dcc3SMatthew G. Knepley 
104781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10479c0f0dcc3SMatthew G. Knepley @*/
10480d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10481d71ae5a4SJacob Faibussowitsch {
10482b665b14eSToby Isaac   PetscLogHandler default_handler;
10483b665b14eSToby Isaac 
104842611ad71SToby Isaac   PetscFunctionBegin;
104852611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10486b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10487b665b14eSToby Isaac   if (default_handler) {
10488c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10489c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10490c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10491c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10492c0f0dcc3SMatthew G. Knepley     const char        *name;
10493c0f0dcc3SMatthew G. Knepley 
104949566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
104959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
104969566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
104979566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10498b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10499c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10500c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10501c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1050263a3b9bcSJacob 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)));
105032611ad71SToby Isaac   } else {
10504b665b14eSToby 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.");
105052611ad71SToby Isaac   }
105063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10507c0f0dcc3SMatthew G. Knepley }
10508