1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11c789d87fSToby Isaac #include <petscblaslapack.h> 12552f7358SJed Brown 13552f7358SJed Brown /* Logging support */ 143b9d9b65SStefano Zampini PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeMultistage, 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_CreateBoxSFC, 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; 15f7b6882eSMatthew G. Knepley PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 16ce78bad3SBarry Smith PetscLogEvent DMPLEX_DistributionView, DMPLEX_DistributionLoad; 17ce78bad3SBarry Smith 18f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 19f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 20f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 21f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 22f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 23f39ec787SMatthew G. Knepley "volume = {38},\n" 24f39ec787SMatthew G. Knepley "number = {5},\n" 25f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 26f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 27f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 28f39ec787SMatthew G. Knepley "year = {2016},\n" 29f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 30f39ec787SMatthew G. Knepley 31d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 32552f7358SJed Brown 33e5337592SStefano Zampini /*@ 349318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 359318fe57SMatthew G. Knepley 369318fe57SMatthew G. Knepley Input Parameter: 37a1cb98faSBarry Smith . dm - The `DMPLEX` object 389318fe57SMatthew G. Knepley 399318fe57SMatthew G. Knepley Output Parameter: 409318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 419318fe57SMatthew G. Knepley 429318fe57SMatthew G. Knepley Level: intermediate 439318fe57SMatthew G. Knepley 44a1cb98faSBarry Smith Note: 45a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 46a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 47a1cb98faSBarry Smith 481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 499318fe57SMatthew G. Knepley @*/ 50d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 51d71ae5a4SJacob Faibussowitsch { 529318fe57SMatthew G. Knepley DMPolytopeType ct; 539318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 549318fe57SMatthew G. Knepley 559318fe57SMatthew G. Knepley PetscFunctionBegin; 569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 579371c9d4SSatish Balay if (cEnd <= cStart) { 589371c9d4SSatish Balay *simplex = PETSC_FALSE; 593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 609371c9d4SSatish Balay } 619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 629318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 649318fe57SMatthew G. Knepley } 659318fe57SMatthew G. Knepley 669318fe57SMatthew G. Knepley /*@ 67412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 68e5337592SStefano Zampini 69d8d19677SJose E. Roman Input Parameters: 70a1cb98faSBarry Smith + dm - The `DMPLEX` object 71412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 72e5337592SStefano Zampini 73e5337592SStefano Zampini Output Parameters: 74ce78bad3SBarry Smith + cStart - The first "normal" cell, pass `NULL` if not needed 75ce78bad3SBarry Smith - cEnd - The upper bound on "normal" cells, pass `NULL` if not needed 76e5337592SStefano Zampini 77412e9a14SMatthew G. Knepley Level: developer 78e5337592SStefano Zampini 79a1cb98faSBarry Smith Note: 805ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 81a1cb98faSBarry Smith 822827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 83e5337592SStefano Zampini @*/ 84ce78bad3SBarry Smith PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PeOp PetscInt *cStart, PeOp PetscInt *cEnd) 85d71ae5a4SJacob Faibussowitsch { 865ae96e2bSMatthew G. Knepley DMLabel ctLabel; 875ae96e2bSMatthew G. Knepley IS valueIS; 885ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 895e27db3eSMatthew G. Knepley PetscBool found = PETSC_FALSE; 901690c2aeSBarry Smith PetscInt Nct, cS = PETSC_INT_MAX, cE = 0; 91e5337592SStefano Zampini 92e5337592SStefano Zampini PetscFunctionBegin; 939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 945ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 955ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 965ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 975ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 98c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 995ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 1005ae96e2bSMatthew G. Knepley 1015ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1025ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1035ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1045ae96e2bSMatthew G. Knepley break; 1055ae96e2bSMatthew G. Knepley } 106c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1075ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1085ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1095ae96e2bSMatthew G. Knepley // Check that a point has the right height 1105ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1115ae96e2bSMatthew G. Knepley if (ht != height) continue; 1125ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1135ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1145e27db3eSMatthew G. Knepley found = PETSC_TRUE; 1155ae96e2bSMatthew G. Knepley } 1165e27db3eSMatthew G. Knepley if (!Nct || !found) cS = cE = 0; 1175ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 118695799ffSMatthew G. Knepley // Reset label for fast lookup 119695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 120412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 121412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 123e5337592SStefano Zampini } 124e5337592SStefano Zampini 125cf58e07aSMatthew G. Knepley PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 126cf58e07aSMatthew G. Knepley { 127cf58e07aSMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 128cf58e07aSMatthew G. Knepley PetscInt *sStart, *sEnd; 129cf58e07aSMatthew G. Knepley PetscViewerVTKFieldType *ft; 130cf58e07aSMatthew G. Knepley PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 131cf58e07aSMatthew G. Knepley DMLabel depthLabel, ctLabel; 132cf58e07aSMatthew G. Knepley 133cf58e07aSMatthew G. Knepley PetscFunctionBegin; 134cf58e07aSMatthew G. Knepley /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 135cf58e07aSMatthew G. Knepley PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 136cf58e07aSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 137cf58e07aSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 138cf58e07aSMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 139cf58e07aSMatthew G. Knepley if (field >= 0) { 140cf58e07aSMatthew G. Knepley if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 141cf58e07aSMatthew G. Knepley } else { 142cf58e07aSMatthew G. Knepley if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 143cf58e07aSMatthew G. Knepley } 144cf58e07aSMatthew G. Knepley 145cf58e07aSMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 146cf58e07aSMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 147cf58e07aSMatthew G. Knepley PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 148cf58e07aSMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 149cf58e07aSMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 150cf58e07aSMatthew G. Knepley const DMPolytopeType ict = (DMPolytopeType)c; 151cf58e07aSMatthew G. Knepley PetscInt dep; 152cf58e07aSMatthew G. Knepley 153cf58e07aSMatthew G. Knepley if (ict == DM_POLYTOPE_FV_GHOST) continue; 154cf58e07aSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 155cf58e07aSMatthew G. Knepley if (pStart >= 0) { 156cf58e07aSMatthew G. Knepley PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 157cf58e07aSMatthew G. Knepley if (dep != depth - cellHeight) continue; 158cf58e07aSMatthew G. Knepley } 159cf58e07aSMatthew G. Knepley if (field >= 0) { 160cf58e07aSMatthew G. Knepley if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 161cf58e07aSMatthew G. Knepley } else { 162cf58e07aSMatthew G. Knepley if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 163cf58e07aSMatthew G. Knepley } 164cf58e07aSMatthew G. Knepley } 165cf58e07aSMatthew G. Knepley 166cf58e07aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 167cf58e07aSMatthew G. Knepley *types = 0; 168cf58e07aSMatthew G. Knepley 169cf58e07aSMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 170cf58e07aSMatthew G. Knepley if (globalvcdof[c]) ++(*types); 171cf58e07aSMatthew G. Knepley } 172cf58e07aSMatthew G. Knepley 173cf58e07aSMatthew G. Knepley PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 174cf58e07aSMatthew G. Knepley t = 0; 175cf58e07aSMatthew G. Knepley if (globalvcdof[DM_NUM_POLYTOPES]) { 176cf58e07aSMatthew G. Knepley sStart[t] = vStart; 177cf58e07aSMatthew G. Knepley sEnd[t] = vEnd; 178cf58e07aSMatthew G. Knepley ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 179cf58e07aSMatthew G. Knepley ++t; 180cf58e07aSMatthew G. Knepley } 181cf58e07aSMatthew G. Knepley 182cf58e07aSMatthew G. Knepley for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 183cf58e07aSMatthew G. Knepley if (globalvcdof[c]) { 184cf58e07aSMatthew G. Knepley const DMPolytopeType ict = (DMPolytopeType)c; 185cf58e07aSMatthew G. Knepley 186cf58e07aSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 187cf58e07aSMatthew G. Knepley sStart[t] = cStart; 188cf58e07aSMatthew G. Knepley sEnd[t] = cEnd; 189cf58e07aSMatthew G. Knepley ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 190cf58e07aSMatthew G. Knepley ++t; 191cf58e07aSMatthew G. Knepley } 192cf58e07aSMatthew G. Knepley } 193cf58e07aSMatthew G. Knepley 194cf58e07aSMatthew G. Knepley if (!*types) { 195cf58e07aSMatthew G. Knepley if (field >= 0) { 196cf58e07aSMatthew G. Knepley const char *fieldname; 197cf58e07aSMatthew G. Knepley 198cf58e07aSMatthew G. Knepley PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 199cf58e07aSMatthew G. Knepley PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 200cf58e07aSMatthew G. Knepley } else { 201cf58e07aSMatthew G. Knepley PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 202cf58e07aSMatthew G. Knepley } 203cf58e07aSMatthew G. Knepley } 204cf58e07aSMatthew G. Knepley 205cf58e07aSMatthew G. Knepley *ssStart = sStart; 206cf58e07aSMatthew G. Knepley *ssEnd = sEnd; 207cf58e07aSMatthew G. Knepley *sft = ft; 208cf58e07aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 209cf58e07aSMatthew G. Knepley } 210cf58e07aSMatthew G. Knepley 211cf58e07aSMatthew G. Knepley PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 212cf58e07aSMatthew G. Knepley { 213cf58e07aSMatthew G. Knepley PetscFunctionBegin; 214cf58e07aSMatthew G. Knepley PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 215cf58e07aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 216cf58e07aSMatthew G. Knepley } 217cf58e07aSMatthew G. Knepley 218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 219d71ae5a4SJacob Faibussowitsch { 220412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 221a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2227e42fee7SMatthew G. Knepley 2237e42fee7SMatthew G. Knepley PetscFunctionBegin; 224e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2279566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2297e42fee7SMatthew G. Knepley if (field >= 0) { 2309566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2319566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2327e42fee7SMatthew G. Knepley } else { 2339566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2349566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2357e42fee7SMatthew G. Knepley } 236462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 237a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2387e42fee7SMatthew G. Knepley *sStart = vStart; 2397e42fee7SMatthew G. Knepley *sEnd = vEnd; 240f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2417e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 242a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2437e42fee7SMatthew G. Knepley *sStart = cStart; 2447e42fee7SMatthew G. Knepley *sEnd = cEnd; 245f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2467e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 247e630c359SToby Isaac } else { 248e630c359SToby Isaac if (field >= 0) { 249e630c359SToby Isaac const char *fieldname; 250e630c359SToby Isaac 2519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 252835f2295SStefano Zampini PetscCall(PetscInfo(dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 253e630c359SToby Isaac } else { 254835f2295SStefano Zampini PetscCall(PetscInfo(dm, "Could not classify VTK output type of section\n")); 255e630c359SToby Isaac } 256e630c359SToby Isaac } 2573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2587e42fee7SMatthew G. Knepley } 2597e42fee7SMatthew G. Knepley 2606913077dSMatthew G. Knepley /*@ 2616913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2626913077dSMatthew G. Knepley 26320f4b53cSBarry Smith Collective 2646913077dSMatthew G. Knepley 2656913077dSMatthew G. Knepley Input Parameters: 266a1cb98faSBarry Smith + dm - The `DMPLEX` object 2676913077dSMatthew G. Knepley . n - The number of vectors 2686913077dSMatthew G. Knepley . u - The array of local vectors 269a1cb98faSBarry Smith - viewer - The `PetscViewer` 2706913077dSMatthew G. Knepley 2716913077dSMatthew G. Knepley Level: advanced 2726913077dSMatthew G. Knepley 2731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2746913077dSMatthew G. Knepley @*/ 275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 276d71ae5a4SJacob Faibussowitsch { 2778926a64eSMatthew G. Knepley DM cdm; 2786913077dSMatthew G. Knepley PetscDS ds; 2796913077dSMatthew G. Knepley PetscDraw draw = NULL; 2806913077dSMatthew G. Knepley PetscDrawLG lg; 2816913077dSMatthew G. Knepley Vec coordinates; 2826913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2836913077dSMatthew G. Knepley PetscReal *vals; 2846913077dSMatthew G. Knepley PetscInt *Nc; 2858926a64eSMatthew G. Knepley PetscInt Nf, Nl, vStart, vEnd, eStart, eEnd; 2866913077dSMatthew G. Knepley char **names; 2876913077dSMatthew G. Knepley 2886913077dSMatthew G. Knepley PetscFunctionBegin; 2898926a64eSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 2909566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2919566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2929566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2939566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2946913077dSMatthew G. Knepley 2959566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2963ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2979566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2986913077dSMatthew G. Knepley 2999566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 3008926a64eSMatthew G. Knepley for (PetscInt i = 0, l = 0; i < n; ++i) { 3016913077dSMatthew G. Knepley const char *vname; 3026913077dSMatthew G. Knepley 3039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 3048926a64eSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 3056913077dSMatthew G. Knepley PetscObject disc; 3066913077dSMatthew G. Knepley const char *fname; 3076913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3086913077dSMatthew G. Knepley 3099566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3106913077dSMatthew G. Knepley /* TODO Create names for components */ 3118926a64eSMatthew G. Knepley for (PetscInt c = 0; c < Nc[f]; ++c, ++l) { 3129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 313c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 314c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 315c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3169566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3176913077dSMatthew G. Knepley } 3186913077dSMatthew G. Knepley } 3196913077dSMatthew G. Knepley } 3209566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3238926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3248926a64eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3258926a64eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 3268926a64eSMatthew G. Knepley PetscSection s; 327e6bf2fb5SMatthew G. Knepley PetscInt cdof, vdof; 3288926a64eSMatthew G. Knepley 3298926a64eSMatthew G. Knepley PetscCall(DMGetLocalSection(dm, &s)); 330e6bf2fb5SMatthew G. Knepley PetscCall(PetscSectionGetDof(s, eStart, &cdof)); 331e6bf2fb5SMatthew G. Knepley PetscCall(PetscSectionGetDof(s, vStart, &vdof)); 332e6bf2fb5SMatthew G. Knepley if (cdof) { 333e6bf2fb5SMatthew G. Knepley if (vdof) { 3348926a64eSMatthew G. Knepley // P_2 3358926a64eSMatthew G. Knepley PetscInt vFirst = -1; 3368926a64eSMatthew G. Knepley 3378926a64eSMatthew G. Knepley for (PetscInt e = eStart; e < eEnd; ++e) { 3388926a64eSMatthew G. Knepley PetscScalar *xa, *xb, *svals; 3398926a64eSMatthew G. Knepley const PetscInt *cone; 3408926a64eSMatthew G. Knepley 3418926a64eSMatthew G. Knepley PetscCall(DMPlexGetCone(dm, e, &cone)); 3428926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(cdm, cone[0], coords, &xa)); 3438926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(cdm, cone[1], coords, &xb)); 3448926a64eSMatthew G. Knepley if (e == eStart) vFirst = cone[0]; 3458926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 3468926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(dm, cone[0], sol[i], &svals)); 3478926a64eSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3488926a64eSMatthew G. Knepley } 3498926a64eSMatthew G. Knepley PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(xa[0]), vals)); 3508926a64eSMatthew G. Knepley if (e == eEnd - 1 && cone[1] != vFirst) { 3518926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 3528926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(dm, e, sol[i], &svals)); 3538926a64eSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3548926a64eSMatthew G. Knepley } 3558926a64eSMatthew G. Knepley PetscCall(PetscDrawLGAddCommonPoint(lg, 0.5 * (PetscRealPart(xa[0]) + PetscRealPart(xb[0])), vals)); 3568926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 3578926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(dm, cone[1], sol[i], &svals)); 3588926a64eSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3598926a64eSMatthew G. Knepley } 3608926a64eSMatthew G. Knepley PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(xb[0]), vals)); 3618926a64eSMatthew G. Knepley } 3628926a64eSMatthew G. Knepley } 3638926a64eSMatthew G. Knepley } else { 364e6bf2fb5SMatthew G. Knepley // P_0 365e6bf2fb5SMatthew G. Knepley for (PetscInt e = eStart; e < eEnd; ++e) { 366e6bf2fb5SMatthew G. Knepley PetscScalar *xa, *xb, *svals; 367e6bf2fb5SMatthew G. Knepley const PetscInt *cone; 368e6bf2fb5SMatthew G. Knepley 369e6bf2fb5SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, e, &cone)); 370e6bf2fb5SMatthew G. Knepley PetscCall(DMPlexPointLocalRead(cdm, cone[0], coords, &xa)); 371e6bf2fb5SMatthew G. Knepley PetscCall(DMPlexPointLocalRead(cdm, cone[1], coords, &xb)); 372e6bf2fb5SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 373e6bf2fb5SMatthew G. Knepley PetscCall(DMPlexPointLocalRead(dm, e, sol[i], &svals)); 374e6bf2fb5SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 375e6bf2fb5SMatthew G. Knepley } 376e6bf2fb5SMatthew G. Knepley PetscCall(PetscDrawLGAddCommonPoint(lg, 0.5 * (PetscRealPart(xa[0]) + PetscRealPart(xb[0])), vals)); 377e6bf2fb5SMatthew G. Knepley } 378e6bf2fb5SMatthew G. Knepley } 379e6bf2fb5SMatthew G. Knepley } else if (vdof) { 3808926a64eSMatthew G. Knepley // P_1 3818926a64eSMatthew G. Knepley for (PetscInt v = vStart; v < vEnd; ++v) { 3826913077dSMatthew G. Knepley PetscScalar *x, *svals; 3836913077dSMatthew G. Knepley 3848926a64eSMatthew G. Knepley PetscCall(DMPlexPointLocalRead(cdm, v, coords, &x)); 3858926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 3869566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3878926a64eSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3886913077dSMatthew G. Knepley } 3899566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3906913077dSMatthew G. Knepley } 391e6bf2fb5SMatthew G. Knepley } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Discretization not supported"); 3929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3938926a64eSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3948926a64eSMatthew G. Knepley for (PetscInt l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3959566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3966913077dSMatthew G. Knepley 3979566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3989566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4006913077dSMatthew G. Knepley } 4016913077dSMatthew G. Knepley 402d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 403d71ae5a4SJacob Faibussowitsch { 4046913077dSMatthew G. Knepley DM dm; 4056913077dSMatthew G. Knepley 4066913077dSMatthew G. Knepley PetscFunctionBegin; 4079566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 4089566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 4093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4106913077dSMatthew G. Knepley } 4116913077dSMatthew G. Knepley 412d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 413d71ae5a4SJacob Faibussowitsch { 414e412dcbdSMatthew G. Knepley DM dm; 415d1df6f1dSMatthew G. Knepley PetscSection s; 416e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 417e412dcbdSMatthew G. Knepley DM cdm; 418e412dcbdSMatthew G. Knepley PetscSection coordSection; 419e412dcbdSMatthew G. Knepley Vec coordinates; 420c9c77995SMatthew G. Knepley const PetscScalar *array; 421c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 422339e3443SMatthew G. Knepley PetscReal vbound[2], time; 4236913077dSMatthew G. Knepley PetscBool flg; 424d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 425e412dcbdSMatthew G. Knepley const char *name; 426339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 427e412dcbdSMatthew G. Knepley 428e412dcbdSMatthew G. Knepley PetscFunctionBegin; 4299566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4309566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 4329566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 4339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 4349566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 4359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 4369566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 4379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 4389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 4399566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 440e412dcbdSMatthew G. Knepley 4419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 4429566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 443e412dcbdSMatthew G. Knepley 4449566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 445c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 4469566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 447e412dcbdSMatthew G. Knepley 448d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 449d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 450d1df6f1dSMatthew G. Knepley DM fdm = dm; 451d1df6f1dSMatthew G. Knepley Vec fv = v; 452d1df6f1dSMatthew G. Knepley IS fis; 453d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 454d1df6f1dSMatthew G. Knepley const char *fname; 455d1df6f1dSMatthew G. Knepley 4569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 4579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 458d1df6f1dSMatthew G. Knepley 4599566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 460ad540459SPierre Jolivet else prefix[0] = '\0'; 461d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4629566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4639566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4649566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4659566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 466d1df6f1dSMatthew G. Knepley } 467d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 468d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 469d1df6f1dSMatthew G. Knepley 4709566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 47163a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 47263a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4739566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 474d1df6f1dSMatthew G. Knepley 475d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 477339e3443SMatthew G. Knepley if (!flg) { 4789566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4799566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 480d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 481339e3443SMatthew G. Knepley } 482c9c77995SMatthew G. Knepley 4839566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4849566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 485c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4869566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 487e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 488b7550097SMatthew G. Knepley DMPolytopeType ct; 48999a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 490c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 491c9c77995SMatthew G. Knepley PetscBool isDG; 4926497c311SBarry Smith PetscInt numCoords; 4936497c311SBarry Smith int color[4] = {-1, -1, -1, -1}; 494e412dcbdSMatthew G. Knepley 495b7550097SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, c, &ct)); 4969566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 497339e3443SMatthew G. Knepley if (a) { 498d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 499339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 500339e3443SMatthew G. Knepley } else { 501339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 502339e3443SMatthew G. Knepley PetscInt numVals, va; 503339e3443SMatthew G. Knepley 5049566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 505b7550097SMatthew G. Knepley if (!numVals) { 506b7550097SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 507b7550097SMatthew G. Knepley continue; 508b7550097SMatthew G. Knepley } 50963a3b9bcSJacob 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); 510d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 511b7550097SMatthew G. Knepley case 1: /* P1 Clamped Segment Prism */ 512b7550097SMatthew G. Knepley case 2: /* P1 Segment Prism, P2 Clamped Segment Prism */ 513b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a tensor segment, but it is a %s", DMPolytopeTypes[ct]); 514b7550097SMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 515b7550097SMatthew G. Knepley break; 516d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 517d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 518b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_TRIANGLE || ct == DM_POLYTOPE_QUADRILATERAL || ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a triangle or quad, but it is a %s", DMPolytopeTypes[ct]); 519d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 520339e3443SMatthew G. Knepley break; 521d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 522d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 523b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_TRIANGLE || ct == DM_POLYTOPE_QUADRILATERAL || ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a triangle or quad, but it is a %s", DMPolytopeTypes[ct]); 524d1df6f1dSMatthew 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]); 525d1df6f1dSMatthew G. Knepley break; 526d71ae5a4SJacob Faibussowitsch default: 527d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 528339e3443SMatthew G. Knepley } 5299566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 530339e3443SMatthew G. Knepley } 531c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 532e412dcbdSMatthew G. Knepley switch (numCoords) { 533e412dcbdSMatthew G. Knepley case 6: 5349edc3542SMatthew Knepley case 12: /* Localized triangle */ 5359566063dSJacob 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])); 536e412dcbdSMatthew G. Knepley break; 537e412dcbdSMatthew G. Knepley case 8: 5389edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 539b7550097SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR) { 540b7550097SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscMax(color[0], color[1]))); 541b7550097SMatthew G. Knepley } else { 5429566063dSJacob 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])); 5439566063dSJacob 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])); 544b7550097SMatthew G. Knepley } 545e412dcbdSMatthew G. Knepley break; 546d71ae5a4SJacob Faibussowitsch default: 547d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 548e412dcbdSMatthew G. Knepley } 549c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 550e412dcbdSMatthew G. Knepley } 5519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 5529566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 5539566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 5549566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 555d1df6f1dSMatthew G. Knepley } 556d1df6f1dSMatthew G. Knepley if (Nf > 1) { 5579566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 5589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 5599566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 560d1df6f1dSMatthew G. Knepley } 561d1df6f1dSMatthew G. Knepley } 5623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 563e412dcbdSMatthew G. Knepley } 564e412dcbdSMatthew G. Knepley 565d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 566d71ae5a4SJacob Faibussowitsch { 5676913077dSMatthew G. Knepley DM dm; 5686913077dSMatthew G. Knepley PetscDraw draw; 5696913077dSMatthew G. Knepley PetscInt dim; 5706913077dSMatthew G. Knepley PetscBool isnull; 5716913077dSMatthew G. Knepley 5726913077dSMatthew G. Knepley PetscFunctionBegin; 5739566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5749566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 5753ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 5766913077dSMatthew G. Knepley 5779566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5796913077dSMatthew G. Knepley switch (dim) { 580d71ae5a4SJacob Faibussowitsch case 1: 581d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 582d71ae5a4SJacob Faibussowitsch break; 583d71ae5a4SJacob Faibussowitsch case 2: 584d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 585d71ae5a4SJacob Faibussowitsch break; 586d71ae5a4SJacob Faibussowitsch default: 587d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5886913077dSMatthew G. Knepley } 5893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5906913077dSMatthew G. Knepley } 5916913077dSMatthew G. Knepley 592d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 593d71ae5a4SJacob Faibussowitsch { 594684b87d9SLisandro Dalcin DM dm; 595684b87d9SLisandro Dalcin Vec locv; 596684b87d9SLisandro Dalcin const char *name; 597684b87d9SLisandro Dalcin PetscSection section; 598684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 599e630c359SToby Isaac PetscInt numFields; 600684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 601684b87d9SLisandro Dalcin 602684b87d9SLisandro Dalcin PetscFunctionBegin; 6039566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 6049566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 6059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6069566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6079566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 6089566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 6099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 610e630c359SToby Isaac if (!numFields) { 6119566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 6129566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 613e630c359SToby Isaac } else { 614e630c359SToby Isaac PetscInt f; 615e630c359SToby Isaac 616e630c359SToby Isaac for (f = 0; f < numFields; f++) { 6179566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 618e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 6199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 6209566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 621e630c359SToby Isaac } 6229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 623e630c359SToby Isaac } 6243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 625684b87d9SLisandro Dalcin } 626684b87d9SLisandro Dalcin 627d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 628d71ae5a4SJacob Faibussowitsch { 629552f7358SJed Brown DM dm; 6308926a64eSMatthew G. Knepley PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns, ispython; 631552f7358SJed Brown 632552f7358SJed Brown PetscFunctionBegin; 6339566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6395f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6408926a64eSMatthew G. Knepley PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 6418926a64eSMatthew G. Knepley if (isvtk || ishdf5 || isdraw || isglvis || iscgns || ispython) { 642684b87d9SLisandro Dalcin PetscInt i, numFields; 643684b87d9SLisandro Dalcin PetscObject fe; 644ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 645684b87d9SLisandro Dalcin Vec locv = v; 646684b87d9SLisandro Dalcin const char *name; 647684b87d9SLisandro Dalcin PetscInt step; 648684b87d9SLisandro Dalcin PetscReal time; 649ef31f671SMatthew G. Knepley 6509566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 651684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 6529566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 6539371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 6549371c9d4SSatish Balay fem = PETSC_TRUE; 6559371c9d4SSatish Balay break; 6569371c9d4SSatish Balay } 657ef31f671SMatthew G. Knepley } 658684b87d9SLisandro Dalcin if (fem) { 659798534f6SMatthew G. Knepley PetscObject isZero; 660798534f6SMatthew G. Knepley 6619566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6639566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6649566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6659566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6669566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 6679566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 6689566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 669ef31f671SMatthew G. Knepley } 670552f7358SJed Brown if (isvtk) { 6719566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 672b136c2c9SMatthew G. Knepley } else if (ishdf5) { 673b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6749566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 675b136c2c9SMatthew G. Knepley #else 676b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 677b136c2c9SMatthew G. Knepley #endif 678f13a32a3SMatthew G. Knepley } else if (isdraw) { 6799566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 6808926a64eSMatthew G. Knepley } else if (ispython) { 6818926a64eSMatthew G. Knepley PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)locv)); 682684b87d9SLisandro Dalcin } else if (isglvis) { 6839566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6849566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6859566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6865f34f2dcSJed Brown } else if (iscgns) { 6875f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6885f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6895f34f2dcSJed Brown #else 6905f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6915f34f2dcSJed Brown #endif 692684b87d9SLisandro Dalcin } 693798534f6SMatthew G. Knepley if (fem) { 6949566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6959566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 696798534f6SMatthew G. Knepley } 697552f7358SJed Brown } else { 698684b87d9SLisandro Dalcin PetscBool isseq; 699684b87d9SLisandro Dalcin 7009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7019566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7029566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 703552f7358SJed Brown } 7043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 705552f7358SJed Brown } 706552f7358SJed Brown 707d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 708d71ae5a4SJacob Faibussowitsch { 709552f7358SJed Brown DM dm; 7108926a64eSMatthew G. Knepley PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns, ispython; 711552f7358SJed Brown 712552f7358SJed Brown PetscFunctionBegin; 7139566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 71428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 7169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 7189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 7195f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 7209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7218926a64eSMatthew G. Knepley PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 7228926a64eSMatthew G. Knepley if (isvtk || isdraw || isglvis || iscgns || ispython) { 723552f7358SJed Brown Vec locv; 724798534f6SMatthew G. Knepley PetscObject isZero; 725552f7358SJed Brown const char *name; 726552f7358SJed Brown 7279566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 7289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 7309566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 7319566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 7329566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 7339566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 7349566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 7359566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 7369566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 737b136c2c9SMatthew G. Knepley } else if (ishdf5) { 738b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7399566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 740b136c2c9SMatthew G. Knepley #else 741b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 742b136c2c9SMatthew G. Knepley #endif 7436823f3c5SBlaise Bourdin } else if (isexodusii) { 7446823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7459566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 7466823f3c5SBlaise Bourdin #else 7476823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7486823f3c5SBlaise Bourdin #endif 749552f7358SJed Brown } else { 750684b87d9SLisandro Dalcin PetscBool isseq; 751684b87d9SLisandro Dalcin 7529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7539566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7549566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 755552f7358SJed Brown } 7563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 757552f7358SJed Brown } 758552f7358SJed Brown 759d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 760d71ae5a4SJacob Faibussowitsch { 761d930f514SMatthew G. Knepley DM dm; 762d930f514SMatthew G. Knepley MPI_Comm comm; 763d930f514SMatthew G. Knepley PetscViewerFormat format; 764d930f514SMatthew G. Knepley Vec v; 765d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 766d930f514SMatthew G. Knepley 767d930f514SMatthew G. Knepley PetscFunctionBegin; 7689566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 7699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 77028b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7719566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 774d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 775a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 776a8ad634aSStefano Zampini /* this need a better fix */ 777a8ad634aSStefano Zampini if (dm->useNatural) { 778d930f514SMatthew G. Knepley const char *vecname; 779d930f514SMatthew G. Knepley PetscInt n, nroots; 780d930f514SMatthew G. Knepley 781966bd95aSPierre Jolivet PetscCheck(dm->sfNatural, comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 7829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 7839566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 784966bd95aSPierre Jolivet PetscCheck(n == nroots, comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 785f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7869566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7879566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 790a8ad634aSStefano Zampini } else v = originalv; 791a8ad634aSStefano Zampini } else v = originalv; 792a8ad634aSStefano Zampini 793d930f514SMatthew G. Knepley if (ishdf5) { 794d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7959566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 796d930f514SMatthew G. Knepley #else 797d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 798d930f514SMatthew G. Knepley #endif 799d930f514SMatthew G. Knepley } else if (isvtk) { 800d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 801d930f514SMatthew G. Knepley } else { 802d930f514SMatthew G. Knepley PetscBool isseq; 803d930f514SMatthew G. Knepley 8049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 8059566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 8069566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 807d930f514SMatthew G. Knepley } 808f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 8093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 810d930f514SMatthew G. Knepley } 811d930f514SMatthew G. Knepley 812d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 813d71ae5a4SJacob Faibussowitsch { 8142c40f234SMatthew G. Knepley DM dm; 8152c40f234SMatthew G. Knepley PetscBool ishdf5; 8162c40f234SMatthew G. Knepley 8172c40f234SMatthew G. Knepley PetscFunctionBegin; 8189566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 81928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 8209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 8212c40f234SMatthew G. Knepley if (ishdf5) { 8222c40f234SMatthew G. Knepley DM dmBC; 8232c40f234SMatthew G. Knepley Vec gv; 8242c40f234SMatthew G. Knepley const char *name; 8252c40f234SMatthew G. Knepley 8269566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 8279566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 8289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 8299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 8309566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 8319566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 8329566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 8339566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 8341baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 8353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8362c40f234SMatthew G. Knepley } 8372c40f234SMatthew G. Knepley 838d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 839d71ae5a4SJacob Faibussowitsch { 8402c40f234SMatthew G. Knepley DM dm; 841472b9844SJames Wright PetscBool ishdf5, isexodusii, iscgns; 8422c40f234SMatthew G. Knepley 8432c40f234SMatthew G. Knepley PetscFunctionBegin; 8449566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 84528b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 8469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 8479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 848472b9844SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 8492c40f234SMatthew G. Knepley if (ishdf5) { 850878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 8519566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 852b136c2c9SMatthew G. Knepley #else 853b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 854878b459fSMatthew G. Knepley #endif 8556823f3c5SBlaise Bourdin } else if (isexodusii) { 8566823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 8579566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 8586823f3c5SBlaise Bourdin #else 8596823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 8606823f3c5SBlaise Bourdin #endif 861472b9844SJames Wright } else if (iscgns) { 862472b9844SJames Wright #if defined(PETSC_HAVE_CGNS) 863472b9844SJames Wright PetscCall(VecLoad_Plex_CGNS_Internal(v, viewer)); 864472b9844SJames Wright #else 865472b9844SJames Wright SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 866472b9844SJames Wright #endif 8671baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 8683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869552f7358SJed Brown } 870552f7358SJed Brown 871d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 872d71ae5a4SJacob Faibussowitsch { 873d930f514SMatthew G. Knepley DM dm; 874d930f514SMatthew G. Knepley PetscViewerFormat format; 875d930f514SMatthew G. Knepley PetscBool ishdf5; 876d930f514SMatthew G. Knepley 877d930f514SMatthew G. Knepley PetscFunctionBegin; 8789566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 87928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 8809566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 8819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 882d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 883a8ad634aSStefano Zampini if (dm->useNatural) { 884d930f514SMatthew G. Knepley if (dm->sfNatural) { 885d930f514SMatthew G. Knepley if (ishdf5) { 886d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 887d930f514SMatthew G. Knepley Vec v; 888d930f514SMatthew G. Knepley const char *vecname; 889d930f514SMatthew G. Knepley 890f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8939566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8949566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8959566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 896f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 897d930f514SMatthew G. Knepley #else 898d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 899d930f514SMatthew G. Knepley #endif 900d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 901d930f514SMatthew G. Knepley } 9021baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 903d930f514SMatthew G. Knepley } 9043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 905d930f514SMatthew G. Knepley } 906d930f514SMatthew G. Knepley 907d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 908d71ae5a4SJacob Faibussowitsch { 909731e8ddeSMatthew G. Knepley PetscSection coordSection; 910731e8ddeSMatthew G. Knepley Vec coordinates; 911ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 912731e8ddeSMatthew G. Knepley const char *name[4]; 913731e8ddeSMatthew G. Knepley const PetscScalar *a; 914731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 915731e8ddeSMatthew G. Knepley 916731e8ddeSMatthew G. Knepley PetscFunctionBegin; 9179566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 9219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 9229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 9249566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 925731e8ddeSMatthew G. Knepley name[0] = "vertex"; 926731e8ddeSMatthew G. Knepley name[1] = "edge"; 927731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 928731e8ddeSMatthew G. Knepley name[dim] = "cell"; 929731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 930731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 931ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 932731e8ddeSMatthew G. Knepley 9339566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 93463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 9359566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 937731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 938731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 939731e8ddeSMatthew G. Knepley 940731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 9419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 942731e8ddeSMatthew G. Knepley if (!dof) continue; 9439566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 9449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 94563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 946731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 9479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 948731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 9499566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 9509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 951731e8ddeSMatthew G. Knepley } 9529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 953731e8ddeSMatthew G. Knepley } 9549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 955731e8ddeSMatthew G. Knepley } 9569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 958731e8ddeSMatthew G. Knepley } 9599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 9603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 961731e8ddeSMatthew G. Knepley } 962731e8ddeSMatthew G. Knepley 9639371c9d4SSatish Balay typedef enum { 9649371c9d4SSatish Balay CS_CARTESIAN, 9659371c9d4SSatish Balay CS_POLAR, 9669371c9d4SSatish Balay CS_CYLINDRICAL, 9679371c9d4SSatish Balay CS_SPHERICAL 9689371c9d4SSatish Balay } CoordSystem; 96919ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 97019ad8254SMatthew G. Knepley 971d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 972d71ae5a4SJacob Faibussowitsch { 97319ad8254SMatthew G. Knepley PetscInt i; 97419ad8254SMatthew G. Knepley 97519ad8254SMatthew G. Knepley PetscFunctionBegin; 97619ad8254SMatthew G. Knepley if (dim > 3) { 9779566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 97819ad8254SMatthew G. Knepley } else { 979bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 98019ad8254SMatthew G. Knepley 98119ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 98219ad8254SMatthew G. Knepley switch (cs) { 9839371c9d4SSatish Balay case CS_CARTESIAN: 9849371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 9859371c9d4SSatish Balay break; 98619ad8254SMatthew G. Knepley case CS_POLAR: 98763a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 98819ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 98919ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 99019ad8254SMatthew G. Knepley break; 99119ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 99263a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 99319ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 99419ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 99519ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 99619ad8254SMatthew G. Knepley break; 99719ad8254SMatthew G. Knepley case CS_SPHERICAL: 99863a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 99919ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 100019ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 100119ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 100219ad8254SMatthew G. Knepley break; 100319ad8254SMatthew G. Knepley } 10049566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 100519ad8254SMatthew G. Knepley } 10063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100719ad8254SMatthew G. Knepley } 100819ad8254SMatthew G. Knepley 1009d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 1010d71ae5a4SJacob Faibussowitsch { 1011552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 10126858538eSMatthew G. Knepley DM cdm, cdmCell; 10136858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 10146858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 1015552f7358SJed Brown PetscViewerFormat format; 1016552f7358SJed Brown 1017552f7358SJed Brown PetscFunctionBegin; 10189566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 1019552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1020552f7358SJed Brown const char *name; 1021f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 10229318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 1023552f7358SJed Brown PetscMPIInt rank, size; 1024552f7358SJed Brown 10259f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10269f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10279f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10289f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10299f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10309f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 10329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 10339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 10349566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 10359566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 10369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10379566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 103863a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 103963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 104063a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 104163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 10429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 104363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 1044552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1045552f7358SJed Brown PetscInt dof, off, s; 1046552f7358SJed Brown 10479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 10489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 104948a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 1050552f7358SJed Brown } 10519566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 105263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 105363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 1054552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1055552f7358SJed Brown PetscInt dof, off, c; 1056552f7358SJed Brown 10579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 10589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 105948a46eb9SPierre 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])); 1060552f7358SJed Brown } 10619566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10633d2e540fSStefano Zampini if (coordSection && coordinates) { 106419ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 10656858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 10661690c2aeSBarry Smith PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_INT_MAX, pcEnd = PETSC_INT_MIN, pStart, pEnd, p; 106719ad8254SMatthew G. Knepley PetscMPIInt rank; 106819ad8254SMatthew G. Knepley const char *name; 106919ad8254SMatthew G. Knepley 10709566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 10719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 10729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 107363a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 10749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 10756858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 10766858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 10776858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 10786858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 10799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 108063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 108163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 10829566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 108319ad8254SMatthew G. Knepley 10849566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 10856858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 10869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 10879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 108819ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 108919ad8254SMatthew G. Knepley PetscInt dof, off; 109019ad8254SMatthew G. Knepley 10916858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10946858538eSMatthew G. Knepley if (dof) { 1095f2719977SBarry Smith PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dof %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10969566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 109819ad8254SMatthew G. Knepley } 10996858538eSMatthew G. Knepley } 11006858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 11016858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 11026858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 11036858538eSMatthew G. Knepley if (dof) { 1104f2719977SBarry Smith PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dof %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 11056858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 11066858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 11076858538eSMatthew G. Knepley } 11086858538eSMatthew G. Knepley } 11096858538eSMatthew G. Knepley } 11109566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 11119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 11129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 11136858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 11143d2e540fSStefano Zampini } 11159566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 11169566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 11179318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 11189318fe57SMatthew G. Knepley DMLabel label; 11199318fe57SMatthew G. Knepley PetscBool isdepth; 11209318fe57SMatthew G. Knepley const char *name; 11219318fe57SMatthew G. Knepley 11229566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 11239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 11249318fe57SMatthew G. Knepley if (isdepth) continue; 11259566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 11269566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 11279318fe57SMatthew G. Knepley } 1128552f7358SJed Brown if (size > 1) { 1129552f7358SJed Brown PetscSF sf; 1130552f7358SJed Brown 11319566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 11329566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1133552f7358SJed Brown } 11341fca310dSJames Wright if (mesh->periodic.face_sfs) 11351fca310dSJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(PetscSFView(mesh->periodic.face_sfs[i], viewer)); 11369566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1137552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 11380588280cSMatthew G. Knepley const char *name, *color; 11390588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 11400588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1141fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1142552f7358SJed Brown PetscReal scale = 2.0; 114378081901SStefano Zampini PetscReal tikzscale = 1.0; 1144b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 11450588280cSMatthew G. Knepley double tcoords[3]; 1146552f7358SJed Brown PetscScalar *coords; 1147b862f699SMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, fStart = 0, fEnd = 0, e, p, n; 1148552f7358SJed Brown PetscMPIInt rank, size; 11490588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1150b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1151fe1cc32dSStefano Zampini PetscBT wp = NULL; 1152fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1153552f7358SJed Brown 11549f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 11559f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 11569f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 11579f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 11589f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 11599f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 11609566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 11619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 11629566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 11630588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 11640588280cSMatthew G. Knepley numColors = 10; 11650588280cSMatthew G. Knepley numLColors = 10; 11669566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 11679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 11689566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 11699566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1170b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1171b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1172b7f6ffafSMatthew G. Knepley n = 4; 11739566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 11741dca8a05SBarry 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); 1175bd3611e6SMatthew G. Knepley n = 4; 11769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 11771dca8a05SBarry 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); 11789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 11790588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 11809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 11810588280cSMatthew G. Knepley if (!useColors) { 11820588280cSMatthew G. Knepley numColors = 3; 11839566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 11840588280cSMatthew G. Knepley } 11859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 11860588280cSMatthew G. Knepley if (!useColors) { 11870588280cSMatthew G. Knepley numLColors = 4; 11889566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11890588280cSMatthew G. Knepley } 11909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1191b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11931dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1194202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1196fe1cc32dSStefano Zampini 1197fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11999566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 12009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 12019566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1202b862f699SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 1203fe1cc32dSStefano Zampini if (lflg) { 1204fe1cc32dSStefano Zampini DMLabel lbl; 1205fe1cc32dSStefano Zampini 12069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1207fe1cc32dSStefano Zampini if (lbl) { 1208fe1cc32dSStefano Zampini PetscInt val, defval; 1209fe1cc32dSStefano Zampini 12109566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 12119566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1212fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1213fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1214fe1cc32dSStefano Zampini PetscInt closureSize; 1215fe1cc32dSStefano Zampini 12169566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1217fe1cc32dSStefano Zampini if (val == defval) continue; 1218fe1cc32dSStefano Zampini 12199566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 122048a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 12219566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1222fe1cc32dSStefano Zampini } 1223fe1cc32dSStefano Zampini } 1224fe1cc32dSStefano Zampini } 1225fe1cc32dSStefano Zampini 12269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 12279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 12289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 12299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 12300588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1231552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1232552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1233552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 12345f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 12350588280cSMatthew G. Knepley if (size > 1) { 12369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1237770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 123863a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 123963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1240770b213bSMatthew G Knepley } 12419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 12420588280cSMatthew G. Knepley } 1243b7f6ffafSMatthew G. Knepley if (drawHasse) { 1244b862f699SMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, PetscMax(fEnd - fStart, cEnd - cStart))); 1245b7f6ffafSMatthew G. Knepley 124663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 124763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 124863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 12499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 125063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 125163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 12529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 125363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 1254b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fStart}{%" PetscInt_FMT "}\n", fStart)); 1255b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fEnd}{%" PetscInt_FMT "}\n", fEnd - 1)); 1256b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fShift}{%.2f}\n", 3 + (maxStratum - (fEnd - fStart)) / 2.)); 1257b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numFaces}{%" PetscInt_FMT "}\n", fEnd - fStart)); 125863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 125963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 126063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 12619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1262b7f6ffafSMatthew G. Knepley } 12639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1264fe1cc32dSStefano Zampini 1265552f7358SJed Brown /* Plot vertices */ 12669566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1268552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1269552f7358SJed Brown PetscInt off, dof, d; 12700588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1271552f7358SJed Brown 1272fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 12739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 12749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 12759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 127663a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 12770588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12780588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1279c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 12800588280cSMatthew G. Knepley } 12810588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12829371c9d4SSatish Balay if (dim == 3) { 12839371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12849371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12859371c9d4SSatish Balay tcoords[2] = -tmp; 12869371c9d4SSatish Balay } 1287552f7358SJed Brown for (d = 0; d < dof; ++d) { 12889566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 1289835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d])); 1290552f7358SJed Brown } 1291b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1292b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 12930588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12940588280cSMatthew G. Knepley PetscInt val; 12959566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12969371c9d4SSatish Balay if (val >= 0) { 12979371c9d4SSatish Balay color = lcolors[l % numLColors]; 12989371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12999371c9d4SSatish Balay break; 13009371c9d4SSatish Balay } 13010588280cSMatthew G. Knepley } 1302b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 130363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1304b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 130563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 13061baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1307552f7358SJed Brown } 13089566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 13099566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1310b7f6ffafSMatthew G. Knepley /* Plot edges */ 1311b7f6ffafSMatthew G. Knepley if (plotEdges) { 13129566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 13139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1314b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1315b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1316b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1317b7f6ffafSMatthew G. Knepley 1318b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 13199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 132063a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 13219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 13229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 13239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 13249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 13259566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1326b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1327835f2295SStefano Zampini tcoords[d] = (double)(scale * PetscRealPart(coords[offA + d] + coords[offB + d]) / 2); 1328b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1329b7f6ffafSMatthew G. Knepley } 1330b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13319371c9d4SSatish Balay if (dim == 3) { 13329371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13339371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13349371c9d4SSatish Balay tcoords[2] = -tmp; 13359371c9d4SSatish Balay } 1336b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 13379566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 1338835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d])); 1339b7f6ffafSMatthew G. Knepley } 1340b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1341b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1342b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1343b7f6ffafSMatthew G. Knepley PetscInt val; 1344bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 13459371c9d4SSatish Balay if (val >= 0) { 13469371c9d4SSatish Balay color = lcolors[l % numLColors]; 13479371c9d4SSatish Balay break; 13489371c9d4SSatish Balay } 1349b7f6ffafSMatthew G. Knepley } 135063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1351b7f6ffafSMatthew G. Knepley } 13529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 13539566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 13549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1355b7f6ffafSMatthew G. Knepley } 1356846a3e8bSMatthew G. Knepley /* Plot cells */ 1357b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1358846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1359846a3e8bSMatthew G. Knepley const PetscInt *cone; 1360846a3e8bSMatthew G. Knepley 1361fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1362846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1363846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1364846a3e8bSMatthew G. Knepley PetscInt val; 13659566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 13669371c9d4SSatish Balay if (val >= 0) { 13679371c9d4SSatish Balay color = lcolors[l % numLColors]; 13689371c9d4SSatish Balay break; 13699371c9d4SSatish Balay } 1370846a3e8bSMatthew G. Knepley } 13719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 137263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1373846a3e8bSMatthew G. Knepley } 1374846a3e8bSMatthew G. Knepley } else { 1375b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1376846a3e8bSMatthew G. Knepley 1377b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1378b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1379fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 13809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1381c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1382b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1383b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1384b7f6ffafSMatthew G. Knepley 13859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 13869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1387b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1388b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1389b7f6ffafSMatthew G. Knepley 13909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 139163a3b9bcSJacob 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)); 1392b7f6ffafSMatthew G. Knepley } 1393b7f6ffafSMatthew G. Knepley } else { 1394b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1395b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1396b7f6ffafSMatthew G. Knepley 13979566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1398846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1399846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1400846a3e8bSMatthew G. Knepley 1401b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1402846a3e8bSMatthew G. Knepley } 14039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1404b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1405b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1406b7f6ffafSMatthew G. Knepley 1407b7f6ffafSMatthew G. Knepley if (v > 0) { 1408b7f6ffafSMatthew G. Knepley if (plotEdges) { 1409b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1410b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1411b7f6ffafSMatthew G. Knepley 14129371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 14139371c9d4SSatish Balay endpoints[1] = vertex; 14149566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 141563a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 141663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 14179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 14181baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1419b7f6ffafSMatthew G. Knepley } 142063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1421b7f6ffafSMatthew G. Knepley } 14229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 14239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1424846a3e8bSMatthew G. Knepley } 1425846a3e8bSMatthew G. Knepley } 1426b7f6ffafSMatthew G. Knepley } 1427846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1428846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1429846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1430c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1431c713ec31SMatthew G. Knepley const PetscScalar *array; 1432c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1433c713ec31SMatthew G. Knepley PetscBool isDG; 1434846a3e8bSMatthew G. Knepley 1435fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1436c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1437c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1438c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 14399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1440c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1441c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1442c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1443846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1444846a3e8bSMatthew G. Knepley } 1445846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 14469371c9d4SSatish Balay if (cdim == 3) { 14479371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 14489371c9d4SSatish Balay tcoords[1] = tcoords[2]; 14499371c9d4SSatish Balay tcoords[2] = -tmp; 14509371c9d4SSatish Balay } 1451ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1452846a3e8bSMatthew G. Knepley } 1453ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1454c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1455c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 14569566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 1457835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", ccoords[d])); 1458846a3e8bSMatthew G. Knepley } 1459b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1460b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1461846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1462846a3e8bSMatthew G. Knepley PetscInt val; 14639566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 14649371c9d4SSatish Balay if (val >= 0) { 14659371c9d4SSatish Balay color = lcolors[l % numLColors]; 14669371c9d4SSatish Balay isLabeled = PETSC_TRUE; 14679371c9d4SSatish Balay break; 14689371c9d4SSatish Balay } 1469846a3e8bSMatthew G. Knepley } 1470b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 147163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1472b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 147363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 14741baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1475846a3e8bSMatthew G. Knepley } 1476b7f6ffafSMatthew G. Knepley if (drawHasse) { 1477b862f699SMatthew G. Knepley int height = 0; 1478b862f699SMatthew G. Knepley 1479b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 14809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 14819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 14829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1483b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,%d) {\\c};\n", rank, color, height++)); 14849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1485552f7358SJed Brown 1486b862f699SMatthew G. Knepley if (depth > 2) { 1487b862f699SMatthew G. Knepley color = colors[1 % numColors]; 1488b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%% Faces\n")); 1489b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\f in {\\fStart,...,\\fEnd}\n")); 1490b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1491b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\f_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\fShift+\\f-\\fStart,%d) {\\f};\n", rank, color, height++)); 1492b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1493b862f699SMatthew G. Knepley } 1494b862f699SMatthew G. Knepley 1495b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 14969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 14979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 14989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1499b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,%d) {\\e};\n", rank, color, height++)); 15009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1501b7f6ffafSMatthew G. Knepley 1502b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 15039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 15049566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 15059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1506b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,%d) {\\v};\n", rank, color, height++)); 15079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1508b7f6ffafSMatthew G. Knepley 1509b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1510b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1511b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1512b7f6ffafSMatthew G. Knepley 15139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 15149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 151548a46eb9SPierre 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)); 15160588280cSMatthew G. Knepley } 15170588280cSMatthew G. Knepley } 15189566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 15199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 15209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 152163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 15229566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 15239566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 15249566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 15259566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 15269566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 15270f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 15280f7d6e4aSStefano Zampini Vec cown, acown; 15290f7d6e4aSStefano Zampini VecScatter sct; 15300f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 15310f7d6e4aSStefano Zampini IS gid, acis; 15320f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 15330f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 15340f7d6e4aSStefano Zampini PetscScalar *array, nid; 15350f7d6e4aSStefano Zampini const PetscInt *idxs; 15360f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 15370f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 15380f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 15390f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 15400f7d6e4aSStefano Zampini 15419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1543b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 15449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 15450f7d6e4aSStefano Zampini #endif 15460f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 15479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 15489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 15490f7d6e4aSStefano Zampini d1 = 0; 15509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 15510f7d6e4aSStefano Zampini nid = d2; 15529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 15539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 15550f7d6e4aSStefano Zampini } else nid = 0.0; 15560f7d6e4aSStefano Zampini 15570f7d6e4aSStefano Zampini /* Get connectivity */ 15589566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15599566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 15600f7d6e4aSStefano Zampini 15610f7d6e4aSStefano Zampini /* filter overlapped local cells */ 15629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 15639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 15649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 15659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 15660f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 15670f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 15680f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 15690f7d6e4aSStefano Zampini } 15709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 157163a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 15729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 15739566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 15740f7d6e4aSStefano Zampini 15750f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 15769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 15779566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 15789566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 15799566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 15800f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 15819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 15829566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 15839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 15849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 15859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 15869566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 15879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 15880f7d6e4aSStefano Zampini 15890f7d6e4aSStefano Zampini /* compute edgeCut */ 15900f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 15919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 15929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 15939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 15949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 15959566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 15960f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 15970f7d6e4aSStefano Zampini PetscInt totl; 15980f7d6e4aSStefano Zampini 15990f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 16009566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 16010f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 16020f7d6e4aSStefano Zampini if (work[i] < 0) { 16030f7d6e4aSStefano Zampini ect += 1; 16040f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 16050f7d6e4aSStefano Zampini } 16060f7d6e4aSStefano Zampini } 16070f7d6e4aSStefano Zampini } 16089566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 16099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 16101690c2aeSBarry Smith lm[0] = numVertices > 0 ? numVertices : PETSC_INT_MAX; 16110f7d6e4aSStefano Zampini lm[1] = -numVertices; 1612462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 1613835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt64_FMT ", min %" PetscInt64_FMT, -((double)gm[1]) / ((double)gm[0]), -gm[1], gm[0])); 16140f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 16150f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 16160f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 1617462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 1618835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt64_FMT ")\n", gm[2])); 1619b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1620835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt64_FMT " (on node %.3f)\n", gm[0] / 2, gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.)); 16210f7d6e4aSStefano Zampini #else 1622835f2295SStefano Zampini PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt64_FMT " (on node %.3f)\n", gm[0] / 2, 0.0)); 16230f7d6e4aSStefano Zampini #endif 16249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 16259566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 16269566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 16279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1628552f7358SJed Brown } else { 1629412e9a14SMatthew G. Knepley const char *name; 1630d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1631412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1632d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1633ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 16349318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1635412e9a14SMatthew G. Knepley MPI_Comm comm; 1636412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1637552f7358SJed Brown 16389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 16409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16419566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 16429566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 16439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 164463a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 164563a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 164663a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 16479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 1648462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 16492827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1650d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 16519566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 16529566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1653412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1654412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1655412e9a14SMatthew G. Knepley 16569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 16579566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1658412e9a14SMatthew G. Knepley ict = ct0; 16599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1660412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1661412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1662412e9a14SMatthew G. Knepley DMPolytopeType ct; 1663412e9a14SMatthew G. Knepley 16649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1665412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1666412e9a14SMatthew G. Knepley else ++Nc[1]; 1667412e9a14SMatthew G. Knepley } 1668ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 16699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 16709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 16719566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 167263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1673834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1674dd400576SPatrick Sanan if (rank == 0) { 167563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 167663a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 167763a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1678834065abSMatthew G. Knepley } 1679cbb7f117SMark Adams } 1680ca7bf7eeSMatthew G. Knepley } else { 1681ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1682ca7bf7eeSMatthew G. Knepley 16839371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 16849371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 16859566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 16869371c9d4SSatish Balay locMinMax[0] = Nc[1]; 16879371c9d4SSatish Balay locMinMax[1] = Nc[1]; 16889566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1689ca7bf7eeSMatthew G. Knepley if (d == depth) { 16909371c9d4SSatish Balay locMinMax[0] = gcNum; 16919371c9d4SSatish Balay locMinMax[1] = gcNum; 16929566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1693ca7bf7eeSMatthew G. Knepley } 169463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 16959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 16969566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 16979566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1698ca7bf7eeSMatthew G. Knepley } 16999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1700552f7358SJed Brown } 17019566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 17029318fe57SMatthew G. Knepley { 17039318fe57SMatthew G. Knepley const PetscReal *maxCell; 17049318fe57SMatthew G. Knepley const PetscReal *L; 17056858538eSMatthew G. Knepley PetscBool localized; 17069318fe57SMatthew G. Knepley 17074fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 17089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 17096858538eSMatthew G. Knepley if (L || localized) { 17106858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 17119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 17126858538eSMatthew G. Knepley if (L) { 17136858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 17149318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 17156858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 17166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 17179318fe57SMatthew G. Knepley } 17186858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 17196858538eSMatthew G. Knepley } 17206858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 17219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 17229318fe57SMatthew G. Knepley } 17239318fe57SMatthew G. Knepley } 17249566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 17259566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1726a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1727a57dd577SMatthew G Knepley DMLabel label; 1728a57dd577SMatthew G Knepley const char *name; 1729281879d4SJames Wright PetscInt *values; 1730a57dd577SMatthew G Knepley PetscInt numValues, v; 1731a57dd577SMatthew G Knepley 17329566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 17339566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 17349566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 173563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 1736281879d4SJames Wright 1737281879d4SJames Wright { // Extract array of DMLabel values so it can be sorted 1738281879d4SJames Wright IS is_values; 1739281879d4SJames Wright const PetscInt *is_values_local = NULL; 1740281879d4SJames Wright 1741281879d4SJames Wright PetscCall(DMLabelGetValueIS(label, &is_values)); 1742281879d4SJames Wright PetscCall(ISGetIndices(is_values, &is_values_local)); 1743281879d4SJames Wright PetscCall(PetscMalloc1(numValues, &values)); 1744281879d4SJames Wright PetscCall(PetscArraycpy(values, is_values_local, numValues)); 1745281879d4SJames Wright PetscCall(PetscSortInt(numValues, values)); 1746281879d4SJames Wright PetscCall(ISRestoreIndices(is_values, &is_values_local)); 1747281879d4SJames Wright PetscCall(ISDestroy(&is_values)); 1748281879d4SJames Wright } 17499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1750a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1751a57dd577SMatthew G Knepley PetscInt size; 1752a57dd577SMatthew G Knepley 17539566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 17549566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 175563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1756a57dd577SMatthew G Knepley } 17579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 17589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 1759281879d4SJames Wright PetscCall(PetscFree(values)); 1760a57dd577SMatthew G Knepley } 1761c1cad2e7SMatthew G. Knepley { 1762c1cad2e7SMatthew G. Knepley char **labelNames; 1763c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1764c1cad2e7SMatthew G. Knepley PetscBool flg; 1765c1cad2e7SMatthew G. Knepley 17669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 17679566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1768c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1769c1cad2e7SMatthew G. Knepley DMLabel label; 1770c1cad2e7SMatthew G. Knepley 17719566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1772c1cad2e7SMatthew G. Knepley if (flg) { 17739566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 17749566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1775c1cad2e7SMatthew G. Knepley } 17769566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1777c1cad2e7SMatthew G. Knepley } 17789566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1779c1cad2e7SMatthew G. Knepley } 178034aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 178134aa8a36SMatthew G. Knepley if (dm->Nf) { 178234aa8a36SMatthew G. Knepley PetscInt f; 178334aa8a36SMatthew G. Knepley 178434aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 178534aa8a36SMatthew G. Knepley const char *name; 178634aa8a36SMatthew G. Knepley 17879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 17889566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 17899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 17909566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 179134aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 17929566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 17939566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 179434aa8a36SMatthew G. Knepley } else { 17959566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 17969566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 179734aa8a36SMatthew G. Knepley } 17989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 179934aa8a36SMatthew G. Knepley } 180034aa8a36SMatthew G. Knepley } 180161f058f9SMatthew G. Knepley DMPlexTransform tr; 180261f058f9SMatthew G. Knepley 180361f058f9SMatthew G. Knepley PetscCall(DMPlexGetTransform(dm, &tr)); 180461f058f9SMatthew G. Knepley if (tr) { 180561f058f9SMatthew G. Knepley PetscCall(PetscViewerASCIIPushTab(viewer)); 180661f058f9SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Created using transform:\n")); 180761f058f9SMatthew G. Knepley PetscCall(DMPlexTransformView(tr, viewer)); 180861f058f9SMatthew G. Knepley PetscCall(PetscViewerASCIIPopTab(viewer)); 180961f058f9SMatthew G. Knepley } 18109566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 18118e7ff633SMatthew G. Knepley if (cdm) { 18129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 18139f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 18149566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 18159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 18168e7ff633SMatthew G. Knepley } 1817552f7358SJed Brown } 18183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1819552f7358SJed Brown } 1820552f7358SJed Brown 182152cfed31SJose E. Roman static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt lC, PetscInt cC, PetscInt cell, const PetscScalar coords[]) 1822d71ae5a4SJacob Faibussowitsch { 1823e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1824e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1825a12d352dSMatthew G. Knepley PetscInt cdim; 182652cfed31SJose E. Roman int lineColor, cellColor; 1827e5c487bfSMatthew G. Knepley 1828e5c487bfSMatthew G. Knepley PetscFunctionBegin; 18299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 18309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 18319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 183252cfed31SJose E. Roman lineColor = (int)(lC < 0 ? PETSC_DRAW_BLACK : lC); 183352cfed31SJose E. Roman cellColor = (int)(cC < 0 ? PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2 : cC); 1834e5c487bfSMatthew G. Knepley switch (ct) { 1835a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1836a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1837a12d352dSMatthew G. Knepley switch (cdim) { 18389371c9d4SSatish Balay case 1: { 1839a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1840a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1841a12d352dSMatthew G. Knepley 1842a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, lineColor)); 1843a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, lineColor)); 1844a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, lineColor)); 18459371c9d4SSatish Balay } break; 18469371c9d4SSatish Balay case 2: { 1847a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1848a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1849a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1850a12d352dSMatthew G. Knepley 1851a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), lineColor)); 1852a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, lineColor)); 1853a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, lineColor)); 18549371c9d4SSatish Balay } break; 1855d71ae5a4SJacob Faibussowitsch default: 1856d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1857a12d352dSMatthew G. Knepley } 1858a12d352dSMatthew G. Knepley break; 1859e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 1860a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), cellColor, cellColor, cellColor)); 1861a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), lineColor)); 1862a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), lineColor)); 1863a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), lineColor)); 1864e5c487bfSMatthew G. Knepley break; 1865e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 1866a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), cellColor, cellColor, cellColor)); 1867a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), cellColor, cellColor, cellColor)); 1868a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), lineColor)); 1869a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), lineColor)); 1870a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), lineColor)); 1871a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), lineColor)); 1872e5c487bfSMatthew G. Knepley break; 18739f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 1874a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), cellColor, cellColor, cellColor)); 1875a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), cellColor, cellColor, cellColor)); 1876a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), lineColor)); 1877a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), lineColor)); 1878a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), lineColor)); 1879a36b0f0fSMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), lineColor)); 18809f4ada15SMatthew G. Knepley break; 1881d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1882d71ae5a4SJacob Faibussowitsch break; 1883d71ae5a4SJacob Faibussowitsch default: 1884d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1885e5c487bfSMatthew G. Knepley } 18863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1887e5c487bfSMatthew G. Knepley } 1888e5c487bfSMatthew G. Knepley 1889c5aedaa3SMatthew 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[]) 1890d71ae5a4SJacob Faibussowitsch { 1891e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1892e5c487bfSMatthew G. Knepley PetscMPIInt rank; 18936497c311SBarry Smith PetscMPIInt fillColor; 1894e5c487bfSMatthew G. Knepley 1895e5c487bfSMatthew G. Knepley PetscFunctionBegin; 18969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1897e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1898c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1899c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1900c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 19019371c9d4SSatish Balay } 1902c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1903e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1904e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1905c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1906c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1907c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1908e5c487bfSMatthew G. Knepley } 19099566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1910c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 19119566063dSJacob 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)); 19129566063dSJacob 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)); 1913e5c487bfSMatthew G. Knepley } 1914e5c487bfSMatthew G. Knepley } 1915c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1916c5aedaa3SMatthew G. Knepley } 1917c5aedaa3SMatthew G. Knepley 1918c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1919c5aedaa3SMatthew G. Knepley { 1920c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1921c5aedaa3SMatthew G. Knepley 1922c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1923c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1924c5aedaa3SMatthew G. Knepley switch (ct) { 1925c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1926c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1927c5aedaa3SMatthew G. Knepley 1928c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1929c5aedaa3SMatthew G. Knepley } break; 1930c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1931c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1932c5aedaa3SMatthew G. Knepley 1933c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 19349371c9d4SSatish Balay } break; 1935d71ae5a4SJacob Faibussowitsch default: 1936d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1937e5c487bfSMatthew G. Knepley } 19383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1939e5c487bfSMatthew G. Knepley } 1940e5c487bfSMatthew G. Knepley 1941d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1942d71ae5a4SJacob Faibussowitsch { 1943e412dcbdSMatthew G. Knepley PetscDraw draw; 1944e412dcbdSMatthew G. Knepley DM cdm; 1945e412dcbdSMatthew G. Knepley PetscSection coordSection; 1946e412dcbdSMatthew G. Knepley Vec coordinates; 1947c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1948e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1949c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1950a36b0f0fSMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv, lineColor = PETSC_DETERMINE, cellColor = PETSC_DETERMINE; 1951e412dcbdSMatthew G. Knepley 1952e412dcbdSMatthew G. Knepley PetscFunctionBegin; 19539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 195463a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1955c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1956c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1957c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 1958a36b0f0fSMatthew G. Knepley PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_line_color", &lineColor, NULL)); 1959a36b0f0fSMatthew G. Knepley PetscCall(PetscOptionsGetInt(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_cell_color", &cellColor, NULL)); 19609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 19619566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 19629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 19639566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 19649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 19659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 19669566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1967e412dcbdSMatthew G. Knepley 19689566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 19699566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 19703ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 19719566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1972e412dcbdSMatthew G. Knepley 1973c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 19749566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 19759566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1976e412dcbdSMatthew G. Knepley 1977cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1978cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1979c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1980ba2698f1SMatthew G. Knepley PetscInt numCoords; 1981c9c77995SMatthew G. Knepley PetscBool isDG; 1982cf3064d3SMatthew G. Knepley 1983c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1984a36b0f0fSMatthew G. Knepley if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, lineColor, cellColor, c, coords)); 19851baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1986c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1987cf3064d3SMatthew G. Knepley } 19889566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 19899566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 19909566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 19919566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 19923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1993e412dcbdSMatthew G. Knepley } 1994e412dcbdSMatthew G. Knepley 1995e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1996e44f6aebSMatthew G. Knepley { 1997e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1998e44f6aebSMatthew G. Knepley PetscFE fe; 1999e44f6aebSMatthew G. Knepley PetscSpace sp; 2000e44f6aebSMatthew G. Knepley PetscClassId id; 2001e44f6aebSMatthew G. Knepley PetscInt degree; 2002e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 2003e44f6aebSMatthew G. Knepley 2004e44f6aebSMatthew G. Knepley PetscFunctionBegin; 2005e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 2006e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 2007e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 2008e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 2009e44f6aebSMatthew G. Knepley *hdm = dm; 2010e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 2011e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 2012e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 2013e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 2014e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 2015e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 2016e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 2017e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 2018e44f6aebSMatthew G. Knepley DM cdm, rcdm; 2019e44f6aebSMatthew G. Knepley Mat In; 2020e44f6aebSMatthew G. Knepley Vec cl, rcl; 2021e44f6aebSMatthew G. Knepley 2022e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 2023e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, PETSC_FALSE)); 2024e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 2025e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 2026e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 2027e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 2028e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 2029e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 2030e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 2031e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 2032e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 2033e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 2034e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 2035e44f6aebSMatthew G. Knepley odm = rdm; 2036e44f6aebSMatthew G. Knepley } 2037e44f6aebSMatthew G. Knepley *hdm = rdm; 2038e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2039e44f6aebSMatthew G. Knepley } 2040e44f6aebSMatthew G. Knepley 20411e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 20421e50132fSMatthew G. Knepley #include <exodusII.h> 20431e50132fSMatthew G. Knepley #endif 20441e50132fSMatthew G. Knepley 2045d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 2046d71ae5a4SJacob Faibussowitsch { 20479f196a02SMartin Diehl PetscBool isascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns, ispython; 2048002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 2049552f7358SJed Brown 2050552f7358SJed Brown PetscFunctionBegin; 2051552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2052552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20539f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 20549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 20559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 20579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 20589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 20595f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 206022d6dc08SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 20619f196a02SMartin Diehl if (isascii) { 20628135c375SStefano Zampini PetscViewerFormat format; 20639566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20641baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 20651baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 2066c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 2067c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20689566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 2069c6ccd67eSMatthew G. Knepley #else 2070c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2071552f7358SJed Brown #endif 2072e412dcbdSMatthew G. Knepley } else if (isvtk) { 20739566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 2074e412dcbdSMatthew G. Knepley } else if (isdraw) { 2075e44f6aebSMatthew G. Knepley DM hdm; 2076e44f6aebSMatthew G. Knepley 2077e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 2078e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 2079e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 20808135c375SStefano Zampini } else if (isglvis) { 20819566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 20821e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 20831e50132fSMatthew G. Knepley } else if (isexodus) { 20846823f3c5SBlaise Bourdin /* 2085caff39ffSPierre Jolivet ExodusII requires that all sets be part of exactly one cell set. 20866823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 2087da81f932SPierre Jolivet with ID 1, containing all cells. 20886823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 20896823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 20906823f3c5SBlaise Bourdin */ 20916823f3c5SBlaise Bourdin PetscInt numCS; 20929566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 20936823f3c5SBlaise Bourdin if (!numCS) { 20941e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 20959566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 20969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 20979566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 20986823f3c5SBlaise Bourdin } 20999566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 21001e50132fSMatthew G. Knepley #endif 21015f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 21025f34f2dcSJed Brown } else if (iscgns) { 21035f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 21045f34f2dcSJed Brown #endif 210522d6dc08SStefano Zampini } else if (ispython) { 210622d6dc08SStefano Zampini PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm)); 21071baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 2108cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 21099566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 2110cb3ba0daSMatthew G. Knepley if (flg) { 2111cb3ba0daSMatthew G. Knepley Vec ranks; 21129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 21139566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 21149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 2115cb3ba0daSMatthew G. Knepley } 2116002a2709SMatthew G. Knepley /* Optionally view a label */ 21179566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 2118002a2709SMatthew G. Knepley if (flg) { 2119002a2709SMatthew G. Knepley DMLabel label; 2120002a2709SMatthew G. Knepley Vec val; 2121002a2709SMatthew G. Knepley 21229566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 212328b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 21249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 21259566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 21269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 2127002a2709SMatthew G. Knepley } 21283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2129552f7358SJed Brown } 2130552f7358SJed Brown 21317f96f51bSksagiyam /*@ 2132a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 21337f96f51bSksagiyam 213420f4b53cSBarry Smith Collective 21357f96f51bSksagiyam 21367f96f51bSksagiyam Input Parameters: 2137a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2138a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 21397f96f51bSksagiyam 21407f96f51bSksagiyam Level: advanced 21417f96f51bSksagiyam 21421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 21437f96f51bSksagiyam @*/ 2144d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2145d71ae5a4SJacob Faibussowitsch { 21467f96f51bSksagiyam PetscBool ishdf5; 21477f96f51bSksagiyam 21487f96f51bSksagiyam PetscFunctionBegin; 21497f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21507f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 21537f96f51bSksagiyam if (ishdf5) { 21547f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 21557f96f51bSksagiyam IS globalPointNumbering; 2156966bd95aSPierre Jolivet PetscViewerFormat format; 21577f96f51bSksagiyam 2158966bd95aSPierre Jolivet PetscCall(PetscViewerGetFormat(viewer, &format)); 2159966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 21609566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21619566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 21637f96f51bSksagiyam #else 21647f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21657f96f51bSksagiyam #endif 21667f96f51bSksagiyam } 21679566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 21683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21697f96f51bSksagiyam } 21707f96f51bSksagiyam 217177b8e257Sksagiyam /*@ 2172a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 217377b8e257Sksagiyam 217420f4b53cSBarry Smith Collective 217577b8e257Sksagiyam 217677b8e257Sksagiyam Input Parameters: 2177a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2178a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 217977b8e257Sksagiyam 218077b8e257Sksagiyam Level: advanced 218177b8e257Sksagiyam 21821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 218377b8e257Sksagiyam @*/ 2184d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2185d71ae5a4SJacob Faibussowitsch { 218677b8e257Sksagiyam PetscBool ishdf5; 218777b8e257Sksagiyam 218877b8e257Sksagiyam PetscFunctionBegin; 218977b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 219077b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 219377b8e257Sksagiyam if (ishdf5) { 219477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 219577b8e257Sksagiyam PetscViewerFormat format; 2196966bd95aSPierre Jolivet 21979566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2198966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 21999566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 220077b8e257Sksagiyam #else 220177b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 220277b8e257Sksagiyam #endif 220377b8e257Sksagiyam } 22049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 22053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 220677b8e257Sksagiyam } 220777b8e257Sksagiyam 2208bd6565f1Sksagiyam /*@ 2209a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2210bd6565f1Sksagiyam 221120f4b53cSBarry Smith Collective 2212bd6565f1Sksagiyam 2213bd6565f1Sksagiyam Input Parameters: 2214a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2215a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2216bd6565f1Sksagiyam 2217bd6565f1Sksagiyam Level: advanced 2218bd6565f1Sksagiyam 22191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2220bd6565f1Sksagiyam @*/ 2221d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2222d71ae5a4SJacob Faibussowitsch { 2223bd6565f1Sksagiyam PetscBool ishdf5; 2224bd6565f1Sksagiyam 2225bd6565f1Sksagiyam PetscFunctionBegin; 2226bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2227bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2230bd6565f1Sksagiyam if (ishdf5) { 2231bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2232bd6565f1Sksagiyam IS globalPointNumbering; 2233bd6565f1Sksagiyam PetscViewerFormat format; 2234bd6565f1Sksagiyam 22359566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2236966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 22379566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 22389566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 22399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 2240bd6565f1Sksagiyam #else 2241bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2242bd6565f1Sksagiyam #endif 2243bd6565f1Sksagiyam } 22449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 22453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2246bd6565f1Sksagiyam } 2247bd6565f1Sksagiyam 2248021affd3Sksagiyam /*@ 2249a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2250021affd3Sksagiyam 225120f4b53cSBarry Smith Collective 2252021affd3Sksagiyam 2253021affd3Sksagiyam Input Parameters: 2254a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2255a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 22560318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2257021affd3Sksagiyam 2258021affd3Sksagiyam Level: advanced 2259021affd3Sksagiyam 2260021affd3Sksagiyam Notes: 2261420bcc1bSBarry 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. 2262021affd3Sksagiyam 22630318f8a0SStefano 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. 2264021affd3Sksagiyam 22651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2266021affd3Sksagiyam @*/ 2267d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2268d71ae5a4SJacob Faibussowitsch { 2269021affd3Sksagiyam PetscBool ishdf5; 2270021affd3Sksagiyam 2271021affd3Sksagiyam PetscFunctionBegin; 2272021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2273021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22740318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2275021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2278021affd3Sksagiyam if (ishdf5) { 2279021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 22809566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2281021affd3Sksagiyam #else 2282021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2283021affd3Sksagiyam #endif 2284021affd3Sksagiyam } 22859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 22863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2287021affd3Sksagiyam } 2288021affd3Sksagiyam 22893e97647fSksagiyam /*@ 22903e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 22913e97647fSksagiyam 229220f4b53cSBarry Smith Collective 22933e97647fSksagiyam 22943e97647fSksagiyam Input Parameters: 2295a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2296a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22970318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 22983e97647fSksagiyam - vec - The global vector to be saved 22993e97647fSksagiyam 23003e97647fSksagiyam Level: advanced 23013e97647fSksagiyam 23023e97647fSksagiyam Notes: 23030318f8a0SStefano 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. 23043e97647fSksagiyam 230560225df5SJacob Faibussowitsch Calling sequence: 2306a1cb98faSBarry Smith .vb 2307a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2308a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2309a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2310a1cb98faSBarry Smith DMClone(dm, §iondm); 2311a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2312a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2313a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2314a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2315a1cb98faSBarry Smith PetscSectionSetUp(section); 2316a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2317a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2318a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2319a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2320a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2321a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2322a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2323a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2324a1cb98faSBarry Smith DMDestroy(§iondm); 2325a1cb98faSBarry Smith DMDestroy(&dm); 2326a1cb98faSBarry Smith .ve 23273e97647fSksagiyam 23281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 23293e97647fSksagiyam @*/ 2330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2331d71ae5a4SJacob Faibussowitsch { 23323e97647fSksagiyam PetscBool ishdf5; 23333e97647fSksagiyam 23343e97647fSksagiyam PetscFunctionBegin; 23353e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23363e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23370318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 23383e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23393e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 23403e97647fSksagiyam /* Check consistency */ 23413e97647fSksagiyam { 23423e97647fSksagiyam PetscSection section; 23433e97647fSksagiyam PetscBool includesConstraints; 23443e97647fSksagiyam PetscInt m, m1; 23453e97647fSksagiyam 23469566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 23489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23499566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23509566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 235163a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 23523e97647fSksagiyam } 23539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 23553e97647fSksagiyam if (ishdf5) { 23563e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23579566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23583e97647fSksagiyam #else 23593e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23603e97647fSksagiyam #endif 23613e97647fSksagiyam } 23629566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 23633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23643e97647fSksagiyam } 23653e97647fSksagiyam 23663e97647fSksagiyam /*@ 23673e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 23683e97647fSksagiyam 236920f4b53cSBarry Smith Collective 23703e97647fSksagiyam 23713e97647fSksagiyam Input Parameters: 2372a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2373a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 23740318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 23753e97647fSksagiyam - vec - The local vector to be saved 23763e97647fSksagiyam 23773e97647fSksagiyam Level: advanced 23783e97647fSksagiyam 2379a1cb98faSBarry Smith Note: 23800318f8a0SStefano 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. 23813e97647fSksagiyam 238260225df5SJacob Faibussowitsch Calling sequence: 2383a1cb98faSBarry Smith .vb 2384a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2385a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2386a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2387a1cb98faSBarry Smith DMClone(dm, §iondm); 2388a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2389a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2390a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2391a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2392a1cb98faSBarry Smith PetscSectionSetUp(section); 2393a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2394a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2395a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2396a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2397a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2398a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2399a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2400a1cb98faSBarry Smith DMDestroy(§iondm); 2401a1cb98faSBarry Smith DMDestroy(&dm); 2402a1cb98faSBarry Smith .ve 24033e97647fSksagiyam 24041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 24053e97647fSksagiyam @*/ 2406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2407d71ae5a4SJacob Faibussowitsch { 24083e97647fSksagiyam PetscBool ishdf5; 24093e97647fSksagiyam 24103e97647fSksagiyam PetscFunctionBegin; 24113e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24123e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24130318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 24143e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24153e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 24163e97647fSksagiyam /* Check consistency */ 24173e97647fSksagiyam { 24183e97647fSksagiyam PetscSection section; 24193e97647fSksagiyam PetscBool includesConstraints; 24203e97647fSksagiyam PetscInt m, m1; 24213e97647fSksagiyam 24229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24239566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24259566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24269566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24283e97647fSksagiyam } 24299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 24313e97647fSksagiyam if (ishdf5) { 24323e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 24339566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 24343e97647fSksagiyam #else 24353e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24363e97647fSksagiyam #endif 24373e97647fSksagiyam } 24389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 24393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24403e97647fSksagiyam } 24413e97647fSksagiyam 2442d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2443d71ae5a4SJacob Faibussowitsch { 2444d4f5a9a0SVaclav Hapla PetscBool ishdf5; 24452c40f234SMatthew G. Knepley 24462c40f234SMatthew G. Knepley PetscFunctionBegin; 24472c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24482c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2450d4f5a9a0SVaclav Hapla if (ishdf5) { 24512c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 24529c48423bSVaclav Hapla PetscViewerFormat format; 24539566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24549c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 24559566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2456509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24579566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 245898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24602c40f234SMatthew G. Knepley #else 24612c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2462552f7358SJed Brown #endif 246398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2464552f7358SJed Brown } 2465552f7358SJed Brown 2466ea8e1828Sksagiyam /*@ 2467a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2468ea8e1828Sksagiyam 246920f4b53cSBarry Smith Collective 2470ea8e1828Sksagiyam 2471ea8e1828Sksagiyam Input Parameters: 2472a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2473a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2474ea8e1828Sksagiyam 24752fe279fdSBarry Smith Output Parameter: 24762c9a7b26SBarry 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; 24772c9a7b26SBarry Smith `NULL` if unneeded 2478dec9e869Sksagiyam 2479ea8e1828Sksagiyam Level: advanced 2480ea8e1828Sksagiyam 24811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2482a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2483ea8e1828Sksagiyam @*/ 2484d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2485d71ae5a4SJacob Faibussowitsch { 2486ea8e1828Sksagiyam PetscBool ishdf5; 2487ea8e1828Sksagiyam 2488ea8e1828Sksagiyam PetscFunctionBegin; 2489ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2490ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24914f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 24929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2494ea8e1828Sksagiyam if (ishdf5) { 2495ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2496ea8e1828Sksagiyam PetscViewerFormat format; 2497966bd95aSPierre Jolivet 24989566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2499966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 25009566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 2501ea8e1828Sksagiyam #else 2502ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2503ea8e1828Sksagiyam #endif 2504ea8e1828Sksagiyam } 25059566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 25063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2507ea8e1828Sksagiyam } 2508ea8e1828Sksagiyam 25093e701f1cSksagiyam /*@ 2510a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 25113e701f1cSksagiyam 251220f4b53cSBarry Smith Collective 25133e701f1cSksagiyam 25143e701f1cSksagiyam Input Parameters: 2515a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2516a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2517a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 25183e701f1cSksagiyam 25193e701f1cSksagiyam Level: advanced 25203e701f1cSksagiyam 25211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2522a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25233e701f1cSksagiyam @*/ 2524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2525d71ae5a4SJacob Faibussowitsch { 25263e701f1cSksagiyam PetscBool ishdf5; 25273e701f1cSksagiyam 25283e701f1cSksagiyam PetscFunctionBegin; 25293e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25303e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2531c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 25329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 25343e701f1cSksagiyam if (ishdf5) { 25353e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 25363e701f1cSksagiyam PetscViewerFormat format; 2537966bd95aSPierre Jolivet 25389566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2539966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 25409566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 25413e701f1cSksagiyam #else 25423e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25433e701f1cSksagiyam #endif 25443e701f1cSksagiyam } 25459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 25463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25473e701f1cSksagiyam } 25483e701f1cSksagiyam 2549b08ad5deSksagiyam /*@ 2550a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2551b08ad5deSksagiyam 255220f4b53cSBarry Smith Collective 2553b08ad5deSksagiyam 2554b08ad5deSksagiyam Input Parameters: 2555a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2556a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 255720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2558b08ad5deSksagiyam 2559b08ad5deSksagiyam Level: advanced 2560b08ad5deSksagiyam 2561a1cb98faSBarry Smith Note: 2562dc9a610eSPierre Jolivet The `PetscSF` argument must not be `NULL` if the `DM` is distributed, otherwise an error occurs. 2563e6368b79SVaclav Hapla 25641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2565a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2566b08ad5deSksagiyam @*/ 2567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2568d71ae5a4SJacob Faibussowitsch { 2569b08ad5deSksagiyam PetscBool ishdf5; 2570b08ad5deSksagiyam 2571b08ad5deSksagiyam PetscFunctionBegin; 2572b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2573b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2574e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 25759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2577b08ad5deSksagiyam if (ishdf5) { 2578b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2579b08ad5deSksagiyam PetscViewerFormat format; 2580b08ad5deSksagiyam 25819566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2582966bd95aSPierre Jolivet PetscCheck(format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 25839566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 2584b08ad5deSksagiyam #else 2585b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2586b08ad5deSksagiyam #endif 2587b08ad5deSksagiyam } 25889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 25893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2590b08ad5deSksagiyam } 2591b08ad5deSksagiyam 2592f84dd6b4Sksagiyam /*@ 2593a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2594f84dd6b4Sksagiyam 259520f4b53cSBarry Smith Collective 2596f84dd6b4Sksagiyam 2597f84dd6b4Sksagiyam Input Parameters: 2598a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2599a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 26000318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2601a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2602f84dd6b4Sksagiyam 2603a4e35b19SJacob Faibussowitsch Output Parameters: 260420f4b53cSBarry 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) 260520f4b53cSBarry 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) 2606f84dd6b4Sksagiyam 2607f84dd6b4Sksagiyam Level: advanced 2608f84dd6b4Sksagiyam 2609f84dd6b4Sksagiyam Notes: 261020f4b53cSBarry 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. 2611f84dd6b4Sksagiyam 26120318f8a0SStefano 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. 2613f84dd6b4Sksagiyam 261420f4b53cSBarry 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. 2615f84dd6b4Sksagiyam 2616f84dd6b4Sksagiyam Example using 2 processes: 2617a1cb98faSBarry Smith .vb 2618a1cb98faSBarry Smith NX (number of points on dm): 4 2619a1cb98faSBarry Smith sectionA : the on-disk section 2620a1cb98faSBarry Smith vecA : a vector associated with sectionA 2621a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2622a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2623a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2624f84dd6b4Sksagiyam 2625a1cb98faSBarry Smith rank 0 rank 1 2626a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2627a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2628a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2629a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2630a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2631a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2632a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2633a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2634a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2635a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2636a1cb98faSBarry Smith .ve 2637a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2638a1cb98faSBarry Smith 26391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2640f84dd6b4Sksagiyam @*/ 2641ce78bad3SBarry Smith PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, PeOp DM sectiondm, PetscSF globalToLocalPointSF, PeOp PetscSF *globalDofSF, PeOp PetscSF *localDofSF) 2642d71ae5a4SJacob Faibussowitsch { 2643f84dd6b4Sksagiyam PetscBool ishdf5; 2644f84dd6b4Sksagiyam 2645f84dd6b4Sksagiyam PetscFunctionBegin; 2646f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2647f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26480318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2649f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2650f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 26514f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 26524f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 26539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2655f84dd6b4Sksagiyam if (ishdf5) { 2656f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 26579566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2658f84dd6b4Sksagiyam #else 2659f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2660f84dd6b4Sksagiyam #endif 2661f84dd6b4Sksagiyam } 26629566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 26633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2664f84dd6b4Sksagiyam } 2665f84dd6b4Sksagiyam 26668be3dfe1Sksagiyam /*@ 26678be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 26688be3dfe1Sksagiyam 266920f4b53cSBarry Smith Collective 26708be3dfe1Sksagiyam 26718be3dfe1Sksagiyam Input Parameters: 2672a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2673a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26740318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2675a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26768be3dfe1Sksagiyam - vec - The global vector to set values of 26778be3dfe1Sksagiyam 26788be3dfe1Sksagiyam Level: advanced 26798be3dfe1Sksagiyam 26808be3dfe1Sksagiyam Notes: 26810318f8a0SStefano 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. 26828be3dfe1Sksagiyam 268360225df5SJacob Faibussowitsch Calling sequence: 2684a1cb98faSBarry Smith .vb 2685a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2686a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2687a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2688a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2689a1cb98faSBarry Smith DMClone(dm, §iondm); 2690a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2691a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2692a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2693a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2694a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2695a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2696a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2697a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2698a1cb98faSBarry Smith DMDestroy(§iondm); 2699a1cb98faSBarry Smith DMDestroy(&dm); 2700a1cb98faSBarry Smith .ve 27018be3dfe1Sksagiyam 27021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2703a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 27048be3dfe1Sksagiyam @*/ 2705d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2706d71ae5a4SJacob Faibussowitsch { 27078be3dfe1Sksagiyam PetscBool ishdf5; 27088be3dfe1Sksagiyam 27098be3dfe1Sksagiyam PetscFunctionBegin; 27108be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27118be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 27120318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 27138be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 27148be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 27158be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 27168be3dfe1Sksagiyam /* Check consistency */ 27178be3dfe1Sksagiyam { 27188be3dfe1Sksagiyam PetscSection section; 27198be3dfe1Sksagiyam PetscBool includesConstraints; 27208be3dfe1Sksagiyam PetscInt m, m1; 27218be3dfe1Sksagiyam 27229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 27239566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 27249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 27259566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 27269566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 272763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 27288be3dfe1Sksagiyam } 27299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 27309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 27318be3dfe1Sksagiyam if (ishdf5) { 27328be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 27339566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 27348be3dfe1Sksagiyam #else 27358be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 27368be3dfe1Sksagiyam #endif 27378be3dfe1Sksagiyam } 27389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 27393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27408be3dfe1Sksagiyam } 27418be3dfe1Sksagiyam 27428be3dfe1Sksagiyam /*@ 27438be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 27448be3dfe1Sksagiyam 274520f4b53cSBarry Smith Collective 27468be3dfe1Sksagiyam 27478be3dfe1Sksagiyam Input Parameters: 2748a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2749a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 27500318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2751a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 27528be3dfe1Sksagiyam - vec - The local vector to set values of 27538be3dfe1Sksagiyam 27548be3dfe1Sksagiyam Level: advanced 27558be3dfe1Sksagiyam 27568be3dfe1Sksagiyam Notes: 27570318f8a0SStefano 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. 27588be3dfe1Sksagiyam 275960225df5SJacob Faibussowitsch Calling sequence: 2760a1cb98faSBarry Smith .vb 2761a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2762a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2763a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2764a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2765a1cb98faSBarry Smith DMClone(dm, §iondm); 2766a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2767a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2768a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2769a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2770a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2771a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2772a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2773a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2774a1cb98faSBarry Smith DMDestroy(§iondm); 2775a1cb98faSBarry Smith DMDestroy(&dm); 2776a1cb98faSBarry Smith .ve 27778be3dfe1Sksagiyam 27781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2779a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 27808be3dfe1Sksagiyam @*/ 2781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2782d71ae5a4SJacob Faibussowitsch { 27838be3dfe1Sksagiyam PetscBool ishdf5; 27848be3dfe1Sksagiyam 27858be3dfe1Sksagiyam PetscFunctionBegin; 27868be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27878be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 27880318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 27898be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 27908be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 27918be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 27928be3dfe1Sksagiyam /* Check consistency */ 27938be3dfe1Sksagiyam { 27948be3dfe1Sksagiyam PetscSection section; 27958be3dfe1Sksagiyam PetscBool includesConstraints; 27968be3dfe1Sksagiyam PetscInt m, m1; 27978be3dfe1Sksagiyam 27989566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 27999566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 28009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 28019566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 28029566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 280363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 28048be3dfe1Sksagiyam } 28059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 28069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 28078be3dfe1Sksagiyam if (ishdf5) { 28088be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 28099566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 28108be3dfe1Sksagiyam #else 28118be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 28128be3dfe1Sksagiyam #endif 28138be3dfe1Sksagiyam } 28149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 28153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28168be3dfe1Sksagiyam } 28178be3dfe1Sksagiyam 2818d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2819d71ae5a4SJacob Faibussowitsch { 2820552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2821552f7358SJed Brown 2822552f7358SJed Brown PetscFunctionBegin; 28239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 28249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 282501468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 282601468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", NULL)); 28279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 28289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 28292e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 28302e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 28312e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 28322e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 28336bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 28346bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2835adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2836adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2837adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2838adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2839c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2840c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2841d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2842d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 28435f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 28443ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 28459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 28469566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 28479566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 28489566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 28499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 28509566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 285121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 28529f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 28539566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 28549566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 28559566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 28561d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 28579566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 28589566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 28599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 28609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 28619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 28621fca310dSJames Wright if (mesh->periodic.face_sfs) { 28631fca310dSJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(PetscSFDestroy(&mesh->periodic.face_sfs[i])); 28641fca310dSJames Wright PetscCall(PetscFree(mesh->periodic.face_sfs)); 28651fca310dSJames Wright } 28666725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 2867b83f62b0SJames Wright if (mesh->periodic.periodic_points) { 2868b83f62b0SJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(ISDestroy(&mesh->periodic.periodic_points[i])); 2869b83f62b0SJames Wright PetscCall(PetscFree(mesh->periodic.periodic_points)); 2870b83f62b0SJames Wright } 28711fca310dSJames Wright if (mesh->periodic.transform) PetscCall(PetscFree(mesh->periodic.transform)); 28729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 28739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 28749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 28759566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 28769566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 28779566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 28789566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 28799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 28809566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 28819566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 28829566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2883c29ce622SStefano Zampini if (mesh->nonempty_comm != MPI_COMM_NULL && mesh->nonempty_comm != MPI_COMM_SELF) PetscCallMPI(MPI_Comm_free(&mesh->nonempty_comm)); 288461f058f9SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->transform)); 2885552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 28869566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 28873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2888552f7358SJed Brown } 2889552f7358SJed Brown 2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2891d71ae5a4SJacob Faibussowitsch { 2892d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2893acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 28949fca9976SJed Brown PetscInt localSize, localStart = 0; 2895837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2896b412c318SBarry Smith MatType mtype; 28971428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2898552f7358SJed Brown 2899552f7358SJed Brown PetscFunctionBegin; 29009566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2901b412c318SBarry Smith mtype = dm->mattype; 2902d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 29039566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 29049566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 29059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 29069fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 29079566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 29089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 29099566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 29109566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 29119566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2912acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 29139566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 29149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 29159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 29169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 29179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 29189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 29199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 29209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2921552f7358SJed Brown if (!isShell) { 29221c6742e7SMatthew G. Knepley // There are three states with pblocks, since block starts can have no dofs: 29231c6742e7SMatthew G. Knepley // UNKNOWN) New Block: An open block has been signalled by pblocks[p] == 1 29241c6742e7SMatthew G. Knepley // TRUE) Block Start: The first entry in a block has been added 29251c6742e7SMatthew G. Knepley // FALSE) Block Add: An additional block entry has been added, since pblocks[p] == 0 29261c6742e7SMatthew G. Knepley PetscBT blst; 29271c6742e7SMatthew G. Knepley PetscBool3 bstate = PETSC_BOOL3_UNKNOWN; 2928837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 29291c6742e7SMatthew G. Knepley const PetscInt *perm = NULL; 29309fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 29311c6742e7SMatthew G. Knepley PetscInt pStart, pEnd, dof, cdof, num_fields; 2932552f7358SJed Brown 29339566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 29341c6742e7SMatthew G. Knepley PetscCall(PetscSectionGetBlockStarts(sectionLocal, &blst)); 29351c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISGetIndices(sectionLocal->perm, &perm)); 29369fca9976SJed Brown 29379fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 29389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2939863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 29401c6742e7SMatthew G. Knepley // We need to process in the permuted order to get block sizes right 29411c6742e7SMatthew G. Knepley for (PetscInt point = pStart; point < pEnd; ++point) { 29421c6742e7SMatthew G. Knepley const PetscInt p = perm ? perm[point] : point; 29431c6742e7SMatthew G. Knepley 2944863027abSJed Brown switch (dm->blocking_type) { 29450e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 29469fca9976SJed Brown PetscInt bdof, offset; 2947a9d99c84SMatthew G. Knepley 29489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 29499fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 29509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 29511c6742e7SMatthew G. Knepley if (blst && PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_UNKNOWN; 295232b27637SMatthew G. Knepley if (dof > 0) { 29531c6742e7SMatthew G. Knepley // State change 29541c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_UNKNOWN) bstate = PETSC_BOOL3_TRUE; 29551c6742e7SMatthew G. Knepley else if (bstate == PETSC_BOOL3_TRUE && blst && !PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_FALSE; 29561c6742e7SMatthew G. Knepley 2957d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2958d02c7345SMatthew G. Knepley // Signal block concatenation 29591c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_FALSE && dof - cdof) pblocks[offset - localStart] = -(dof - cdof); 296032b27637SMatthew G. Knepley } 29611d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 29621d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 29631d17a0a3SMatthew G. Knepley if (dof) { 29649371c9d4SSatish Balay if (bs < 0) { 29659371c9d4SSatish Balay bs = bdof; 29669371c9d4SSatish Balay } else if (bs != bdof) { 29679371c9d4SSatish Balay bs = 1; 29689371c9d4SSatish Balay } 2969552f7358SJed Brown } 2970863027abSJed Brown } break; 2971863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2972863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2973863027abSJed Brown PetscInt num_comp, bdof, offset; 2974863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2975863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2976863027abSJed Brown if (dof < 0) continue; 2977863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2978863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2979863027abSJed 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); 2980863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2981863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2982863027abSJed Brown // Handle possibly constant block size (unlikely) 2983863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2984863027abSJed Brown if (dof) { 2985863027abSJed Brown if (bs < 0) { 2986863027abSJed Brown bs = bdof; 2987863027abSJed Brown } else if (bs != bdof) { 2988863027abSJed Brown bs = 1; 2989863027abSJed Brown } 2990863027abSJed Brown } 2991863027abSJed Brown } 2992863027abSJed Brown } break; 2993863027abSJed Brown } 29942a28c762SMatthew G Knepley } 29951c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISRestoreIndices(sectionLocal->perm, &perm)); 29962a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 29971690c2aeSBarry Smith bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs; 2998e432b41dSStefano Zampini bsLocal[1] = bs; 29999566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 3000e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 3001e432b41dSStefano Zampini else bs = bsMinMax[0]; 30026fd5c86aSStefano Zampini bs = PetscMax(1, bs); 30039566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 30040682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 30059566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 30069566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 30070682b8bbSJed Brown } else { 30089566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 30099566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 30109566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 3011552f7358SJed Brown } 301232b27637SMatthew G. Knepley if (pblocks) { // Consolidate blocks 30139fca9976SJed Brown PetscInt nblocks = 0; 301432b27637SMatthew G. Knepley pblocks[0] = PetscAbs(pblocks[0]); 30159fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 30169fca9976SJed Brown if (pblocks[i] == 0) continue; 3017d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 3018d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 3019d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 3020d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 3021d02c7345SMatthew G. Knepley } else { 30229fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 3023d02c7345SMatthew G. Knepley } 30241c6742e7SMatthew G. Knepley for (PetscInt j = 1; j < pblocks[i]; j++) 30251c6742e7SMatthew G. Knepley PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " at %" PetscInt_FMT " mismatches entry %" PetscInt_FMT " at %" PetscInt_FMT, pblocks[i], i, pblocks[i + j], i + j); 30269fca9976SJed Brown } 30279fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 30289fca9976SJed Brown } 30299fca9976SJed Brown PetscCall(PetscFree(pblocks)); 3030aa0f6e3cSJed Brown } 30319566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 30323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3033552f7358SJed Brown } 3034552f7358SJed Brown 30357cd05799SMatthew G. Knepley /*@ 3036a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 3037be36d101SStefano Zampini 3038a1cb98faSBarry Smith Not Collective 3039be36d101SStefano Zampini 3040be36d101SStefano Zampini Input Parameter: 304160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 3042be36d101SStefano Zampini 30432fe279fdSBarry Smith Output Parameter: 3044be36d101SStefano Zampini . subsection - The subdomain section 3045be36d101SStefano Zampini 3046be36d101SStefano Zampini Level: developer 3047be36d101SStefano Zampini 30481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 30497cd05799SMatthew G. Knepley @*/ 3050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 3051d71ae5a4SJacob Faibussowitsch { 3052be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 3053be36d101SStefano Zampini 3054be36d101SStefano Zampini PetscFunctionBegin; 3055be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3056be36d101SStefano Zampini if (!mesh->subdomainSection) { 3057be36d101SStefano Zampini PetscSection section; 3058be36d101SStefano Zampini PetscSF sf; 3059be36d101SStefano Zampini 30609566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 30619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 3062eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 30639566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 3064be36d101SStefano Zampini } 3065be36d101SStefano Zampini *subsection = mesh->subdomainSection; 30663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3067be36d101SStefano Zampini } 3068be36d101SStefano Zampini 3069552f7358SJed Brown /*@ 307020f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 3071552f7358SJed Brown 3072a1cb98faSBarry Smith Not Collective 3073552f7358SJed Brown 3074552f7358SJed Brown Input Parameter: 307560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 3076552f7358SJed Brown 3077552f7358SJed Brown Output Parameters: 3078552f7358SJed Brown + pStart - The first mesh point 3079552f7358SJed Brown - pEnd - The upper bound for mesh points 3080552f7358SJed Brown 3081552f7358SJed Brown Level: beginner 3082552f7358SJed Brown 30831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 3084552f7358SJed Brown @*/ 3085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 3086d71ae5a4SJacob Faibussowitsch { 3087552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3088552f7358SJed Brown 3089552f7358SJed Brown PetscFunctionBegin; 3090552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30919f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 30929f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 30933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3094552f7358SJed Brown } 3095552f7358SJed Brown 3096552f7358SJed Brown /*@ 309720f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 3098552f7358SJed Brown 3099a1cb98faSBarry Smith Not Collective 3100552f7358SJed Brown 3101552f7358SJed Brown Input Parameters: 310260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3103552f7358SJed Brown . pStart - The first mesh point 3104552f7358SJed Brown - pEnd - The upper bound for mesh points 3105552f7358SJed Brown 3106552f7358SJed Brown Level: beginner 3107552f7358SJed Brown 31081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 3109552f7358SJed Brown @*/ 3110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 3111d71ae5a4SJacob Faibussowitsch { 3112552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3113552f7358SJed Brown 3114552f7358SJed Brown PetscFunctionBegin; 3115552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 31179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 311821027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 31193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3120552f7358SJed Brown } 3121552f7358SJed Brown 3122552f7358SJed Brown /*@ 3123eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 3124552f7358SJed Brown 3125a1cb98faSBarry Smith Not Collective 3126552f7358SJed Brown 3127552f7358SJed Brown Input Parameters: 312860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3129a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3130552f7358SJed Brown 3131552f7358SJed Brown Output Parameter: 313220f4b53cSBarry Smith . size - The cone size for point `p` 3133552f7358SJed Brown 3134552f7358SJed Brown Level: beginner 3135552f7358SJed Brown 31361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3137552f7358SJed Brown @*/ 3138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 3139d71ae5a4SJacob Faibussowitsch { 3140552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3141552f7358SJed Brown 3142552f7358SJed Brown PetscFunctionBegin; 3143552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31444f572ea9SToby Isaac PetscAssertPointer(size, 3); 31459f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 31469f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 31473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3148552f7358SJed Brown } 3149552f7358SJed Brown 3150552f7358SJed Brown /*@ 3151eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 3152552f7358SJed Brown 3153a1cb98faSBarry Smith Not Collective 3154552f7358SJed Brown 3155552f7358SJed Brown Input Parameters: 315660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3157a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 315820f4b53cSBarry Smith - size - The cone size for point `p` 3159552f7358SJed Brown 3160552f7358SJed Brown Level: beginner 3161552f7358SJed Brown 3162a1cb98faSBarry Smith Note: 3163a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3164a1cb98faSBarry Smith 31652c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3166552f7358SJed Brown @*/ 3167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3168d71ae5a4SJacob Faibussowitsch { 3169552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3170552f7358SJed Brown 3171552f7358SJed Brown PetscFunctionBegin; 3172552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31739f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 31753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3176552f7358SJed Brown } 3177552f7358SJed Brown 3178552f7358SJed Brown /*@C 3179eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3180552f7358SJed Brown 3181a1cb98faSBarry Smith Not Collective 3182552f7358SJed Brown 3183552f7358SJed Brown Input Parameters: 3184a1cb98faSBarry Smith + dm - The `DMPLEX` 3185a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3186552f7358SJed Brown 3187552f7358SJed Brown Output Parameter: 31882c9a7b26SBarry Smith . cone - An array of points which are on the in-edges for point `p`, the length of `cone` is the result of `DMPlexGetConeSize()` 3189552f7358SJed Brown 3190552f7358SJed Brown Level: beginner 3191552f7358SJed Brown 319260225df5SJacob Faibussowitsch Fortran Notes: 31932c9a7b26SBarry Smith `cone` must be declared with 31942c9a7b26SBarry Smith .vb 31952c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 31962c9a7b26SBarry Smith .ve 31972c9a7b26SBarry Smith 3198feaf08eaSBarry Smith You must call `DMPlexRestoreCone()` after you finish using the array. 3199a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 32003813dfbdSMatthew G Knepley 32011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3202552f7358SJed Brown @*/ 3203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3204d71ae5a4SJacob Faibussowitsch { 3205552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3206552f7358SJed Brown PetscInt off; 3207552f7358SJed Brown 3208552f7358SJed Brown PetscFunctionBegin; 3209552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32104f572ea9SToby Isaac PetscAssertPointer(cone, 3); 32119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 32128e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 32133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3214552f7358SJed Brown } 3215552f7358SJed Brown 3216cc4c1da9SBarry Smith /*@ 32170ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 32180ce7577fSVaclav Hapla 3219a1cb98faSBarry Smith Not Collective 32200ce7577fSVaclav Hapla 32210ce7577fSVaclav Hapla Input Parameters: 3222a1cb98faSBarry Smith + dm - The `DMPLEX` 3223a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 32240ce7577fSVaclav Hapla 3225d8d19677SJose E. Roman Output Parameters: 322620f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 32272c9a7b26SBarry Smith - pCones - An `IS` containing the points which are on the in-edges for the point set `p` 32280ce7577fSVaclav Hapla 32290ce7577fSVaclav Hapla Level: intermediate 32300ce7577fSVaclav Hapla 32311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 32320ce7577fSVaclav Hapla @*/ 3233ce78bad3SBarry Smith PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PeOp PetscSection *pConesSection, PeOp IS *pCones) 3234d71ae5a4SJacob Faibussowitsch { 32350ce7577fSVaclav Hapla PetscSection cs, newcs; 32360ce7577fSVaclav Hapla PetscInt *cones; 32370ce7577fSVaclav Hapla PetscInt *newarr = NULL; 32380ce7577fSVaclav Hapla PetscInt n; 32390ce7577fSVaclav Hapla 32400ce7577fSVaclav Hapla PetscFunctionBegin; 32419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 32429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 32439566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 32440ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 32450ce7577fSVaclav Hapla if (pCones) { 32469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 32479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 32480ce7577fSVaclav Hapla } 32493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32500ce7577fSVaclav Hapla } 32510ce7577fSVaclav Hapla 3252af9eab45SVaclav Hapla /*@ 3253af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3254d4636a37SVaclav Hapla 3255a1cb98faSBarry Smith Not Collective 3256d4636a37SVaclav Hapla 3257d4636a37SVaclav Hapla Input Parameters: 3258a1cb98faSBarry Smith + dm - The `DMPLEX` 3259a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3260d4636a37SVaclav Hapla 3261d4636a37SVaclav Hapla Output Parameter: 32622c9a7b26SBarry Smith . expandedPoints - An `IS` containing the of vertices recursively expanded from input points 3263d4636a37SVaclav Hapla 3264d4636a37SVaclav Hapla Level: advanced 3265d4636a37SVaclav Hapla 3266af9eab45SVaclav Hapla Notes: 326720f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3268af9eab45SVaclav Hapla 3269a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3270a1cb98faSBarry Smith 32711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3272a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3273d4636a37SVaclav Hapla @*/ 3274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3275d71ae5a4SJacob Faibussowitsch { 3276af9eab45SVaclav Hapla IS *expandedPointsAll; 3277af9eab45SVaclav Hapla PetscInt depth; 3278d4636a37SVaclav Hapla 3279d4636a37SVaclav Hapla PetscFunctionBegin; 3280af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3281af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 32824f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 32839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3284af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 32859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 32869566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 32873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3288af9eab45SVaclav Hapla } 3289af9eab45SVaclav Hapla 3290af9eab45SVaclav Hapla /*@ 32912c9a7b26SBarry Smith DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices 32922c9a7b26SBarry Smith (DAG points of depth 0, i.e., without cones). 3293af9eab45SVaclav Hapla 3294a1cb98faSBarry Smith Not Collective 3295af9eab45SVaclav Hapla 3296af9eab45SVaclav Hapla Input Parameters: 3297a1cb98faSBarry Smith + dm - The `DMPLEX` 3298a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3299af9eab45SVaclav Hapla 3300d8d19677SJose E. Roman Output Parameters: 3301a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3302af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3303af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3304af9eab45SVaclav Hapla 3305af9eab45SVaclav Hapla Level: advanced 3306af9eab45SVaclav Hapla 3307af9eab45SVaclav Hapla Notes: 3308a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3309af9eab45SVaclav Hapla 3310a4e35b19SJacob 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. 3311af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3312af9eab45SVaclav Hapla 3313a4e35b19SJacob 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\: 3314a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3315a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3316af9eab45SVaclav Hapla 33171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3318a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3319af9eab45SVaclav Hapla @*/ 3320ce78bad3SBarry Smith PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PeOp PetscInt *depth, PeOp IS *expandedPoints[], PeOp PetscSection *sections[]) 3321d71ae5a4SJacob Faibussowitsch { 3322af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3323af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3324af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3325af9eab45SVaclav Hapla IS *expandedPoints_; 3326af9eab45SVaclav Hapla PetscSection *sections_; 3327af9eab45SVaclav Hapla 3328af9eab45SVaclav Hapla PetscFunctionBegin; 3329af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3330af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 33314f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 33324f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 33334f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 33349566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 33359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 33369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 33379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 33389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3339af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3340af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 33419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 33429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3343af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 33449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3345af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 33469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 33479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3348af9eab45SVaclav Hapla } else { 33499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3350af9eab45SVaclav Hapla } 3351af9eab45SVaclav Hapla } 33529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 33539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 33549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3355af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 33569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 33579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3358af9eab45SVaclav Hapla if (cn > 1) { 33599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 3360418fb43bSPierre Jolivet PetscCall(PetscArraycpy(&newarr[co], cone, cn)); 3361af9eab45SVaclav Hapla } else { 3362af9eab45SVaclav Hapla newarr[co] = arr[i]; 3363af9eab45SVaclav Hapla } 3364af9eab45SVaclav Hapla } 33659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3366af9eab45SVaclav Hapla arr = newarr; 3367af9eab45SVaclav Hapla n = newn; 3368af9eab45SVaclav Hapla } 33699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3370af9eab45SVaclav Hapla *depth = depth_; 3371af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3372af9eab45SVaclav Hapla else { 33739566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 33749566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3375af9eab45SVaclav Hapla } 3376af9eab45SVaclav Hapla if (sections) *sections = sections_; 3377af9eab45SVaclav Hapla else { 33789566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 33799566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3380af9eab45SVaclav Hapla } 33813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3382af9eab45SVaclav Hapla } 3383af9eab45SVaclav Hapla 3384af9eab45SVaclav Hapla /*@ 3385a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3386af9eab45SVaclav Hapla 3387a1cb98faSBarry Smith Not Collective 3388af9eab45SVaclav Hapla 3389af9eab45SVaclav Hapla Input Parameters: 3390a1cb98faSBarry Smith + dm - The `DMPLEX` 3391a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3392af9eab45SVaclav Hapla 3393d8d19677SJose E. Roman Output Parameters: 3394a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3395af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3396af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3397af9eab45SVaclav Hapla 3398af9eab45SVaclav Hapla Level: advanced 3399af9eab45SVaclav Hapla 3400a1cb98faSBarry Smith Note: 3401a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3402af9eab45SVaclav Hapla 34031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3404a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3405af9eab45SVaclav Hapla @*/ 3406ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PeOp PetscInt *depth, PeOp IS *expandedPoints[], PeOp PetscSection *sections[]) 3407d71ae5a4SJacob Faibussowitsch { 3408af9eab45SVaclav Hapla PetscInt d, depth_; 3409af9eab45SVaclav Hapla 3410af9eab45SVaclav Hapla PetscFunctionBegin; 34119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 34121dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3413af9eab45SVaclav Hapla if (depth) *depth = 0; 3414af9eab45SVaclav Hapla if (expandedPoints) { 341557508eceSPierre Jolivet for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&(*expandedPoints)[d])); 34169566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3417af9eab45SVaclav Hapla } 3418af9eab45SVaclav Hapla if (sections) { 341957508eceSPierre Jolivet for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&(*sections)[d])); 34209566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3421af9eab45SVaclav Hapla } 34223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3423d4636a37SVaclav Hapla } 3424d4636a37SVaclav Hapla 3425552f7358SJed Brown /*@ 342692371b87SBarry 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 3427552f7358SJed Brown 3428a1cb98faSBarry Smith Not Collective 3429552f7358SJed Brown 3430552f7358SJed Brown Input Parameters: 343160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3432a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34332c9a7b26SBarry Smith - cone - An array of points which are on the in-edges for point `p`, its length must have been previously provided with `DMPlexSetConeSize()` 3434552f7358SJed Brown 3435552f7358SJed Brown Level: beginner 3436552f7358SJed Brown 3437a1cb98faSBarry Smith Note: 3438a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3439a1cb98faSBarry Smith 34401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3441552f7358SJed Brown @*/ 3442d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3443d71ae5a4SJacob Faibussowitsch { 3444552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3445552f7358SJed Brown PetscInt dof, off, c; 3446552f7358SJed Brown 3447552f7358SJed Brown PetscFunctionBegin; 3448552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34504f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 34519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3452db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3453db485b19SStefano Zampini PetscInt pStart, pEnd; 3454db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345563a3b9bcSJacob 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); 3456552f7358SJed Brown for (c = 0; c < dof; ++c) { 345763a3b9bcSJacob 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); 3458552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3459552f7358SJed Brown } 3460db485b19SStefano Zampini } else { 3461db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3462db485b19SStefano Zampini } 34633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3464552f7358SJed Brown } 3465552f7358SJed Brown 3466552f7358SJed Brown /*@C 3467eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3468552f7358SJed Brown 3469a1cb98faSBarry Smith Not Collective 3470552f7358SJed Brown 3471552f7358SJed Brown Input Parameters: 347260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3473a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3474552f7358SJed Brown 3475552f7358SJed Brown Output Parameter: 347620f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 34772c9a7b26SBarry Smith integer giving the prescription for cone traversal. Its length is given by the result of `DMPlexSetConeSize()` 3478552f7358SJed Brown 3479552f7358SJed Brown Level: beginner 3480552f7358SJed Brown 3481a1cb98faSBarry Smith Note: 3482b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3483b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3484a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3485b5a892a1SMatthew G. Knepley with the identity. 3486b5a892a1SMatthew G. Knepley 348760225df5SJacob Faibussowitsch Fortran Notes: 34882c9a7b26SBarry Smith You must call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3489a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 34903813dfbdSMatthew G Knepley 34912c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetConeSize()`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, 34922c9a7b26SBarry Smith `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3493552f7358SJed Brown @*/ 3494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3495d71ae5a4SJacob Faibussowitsch { 3496552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3497552f7358SJed Brown PetscInt off; 3498552f7358SJed Brown 3499552f7358SJed Brown PetscFunctionBegin; 3500552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 350176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3502552f7358SJed Brown PetscInt dof; 35039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35044f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3505552f7358SJed Brown } 35069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35070d644c17SKarl Rupp 3508552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 35093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3510552f7358SJed Brown } 3511552f7358SJed Brown 3512552f7358SJed Brown /*@ 3513eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3514552f7358SJed Brown 3515a1cb98faSBarry Smith Not Collective 3516552f7358SJed Brown 3517552f7358SJed Brown Input Parameters: 351860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3519a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35202c9a7b26SBarry Smith - coneOrientation - An array of orientations. Its length is given by the result of `DMPlexSetConeSize()` 3521b5a892a1SMatthew G. Knepley 3522552f7358SJed Brown Level: beginner 3523552f7358SJed Brown 3524a1cb98faSBarry Smith Notes: 3525a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3526a1cb98faSBarry Smith 3527a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3528a1cb98faSBarry Smith 35291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3530552f7358SJed Brown @*/ 3531d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3532d71ae5a4SJacob Faibussowitsch { 3533552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3534552f7358SJed Brown PetscInt pStart, pEnd; 3535552f7358SJed Brown PetscInt dof, off, c; 3536552f7358SJed Brown 3537552f7358SJed Brown PetscFunctionBegin; 3538552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35404f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 35419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3542db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3543db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 354463a3b9bcSJacob 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); 3545552f7358SJed Brown for (c = 0; c < dof; ++c) { 3546552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3547552f7358SJed Brown 35489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 35491dca8a05SBarry 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); 3550552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3551552f7358SJed Brown } 3552db485b19SStefano Zampini } else { 3553db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3554db485b19SStefano Zampini } 35553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3556552f7358SJed Brown } 3557552f7358SJed Brown 35587cd05799SMatthew G. Knepley /*@ 3559eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 35607cd05799SMatthew G. Knepley 3561a1cb98faSBarry Smith Not Collective 35627cd05799SMatthew G. Knepley 35637cd05799SMatthew G. Knepley Input Parameters: 356460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3565a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35667cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 35677cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 35687cd05799SMatthew G. Knepley 35697cd05799SMatthew G. Knepley Level: beginner 35707cd05799SMatthew G. Knepley 35711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 35727cd05799SMatthew G. Knepley @*/ 3573d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3574d71ae5a4SJacob Faibussowitsch { 3575552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3576552f7358SJed Brown PetscInt pStart, pEnd; 3577552f7358SJed Brown PetscInt dof, off; 3578552f7358SJed Brown 3579552f7358SJed Brown PetscFunctionBegin; 3580552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3581a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 35829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 358363a3b9bcSJacob 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); 358463a3b9bcSJacob 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); 35859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 358663a3b9bcSJacob 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); 3587a03d55ffSStefano Zampini } 3588a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3589552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 35903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3591552f7358SJed Brown } 3592552f7358SJed Brown 35937cd05799SMatthew G. Knepley /*@ 3594eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 35957cd05799SMatthew G. Knepley 3596a1cb98faSBarry Smith Not Collective 35977cd05799SMatthew G. Knepley 35987cd05799SMatthew G. Knepley Input Parameters: 359960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3600a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36017cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 36027cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 36037cd05799SMatthew G. Knepley 36047cd05799SMatthew G. Knepley Level: beginner 36057cd05799SMatthew G. Knepley 3606a1cb98faSBarry Smith Note: 3607a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3608b5a892a1SMatthew G. Knepley 36091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36107cd05799SMatthew G. Knepley @*/ 3611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3612d71ae5a4SJacob Faibussowitsch { 361377c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 361477c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 361577c88f5bSMatthew G Knepley PetscInt dof, off; 361677c88f5bSMatthew G Knepley 361777c88f5bSMatthew G Knepley PetscFunctionBegin; 361877c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3619a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 36209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 362163a3b9bcSJacob 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); 36229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 362363a3b9bcSJacob 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); 3624a03d55ffSStefano Zampini } 3625a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 362677c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 36273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 362877c88f5bSMatthew G Knepley } 362977c88f5bSMatthew G Knepley 36309f4ada15SMatthew G. Knepley /*@C 36319f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 36329f4ada15SMatthew G. Knepley 36339f4ada15SMatthew G. Knepley Not collective 36349f4ada15SMatthew G. Knepley 36359f4ada15SMatthew G. Knepley Input Parameters: 36369f4ada15SMatthew G. Knepley + dm - The DMPlex 36379f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 36389f4ada15SMatthew G. Knepley 36399f4ada15SMatthew G. Knepley Output Parameters: 364020f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 364120f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 36429f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 36439f4ada15SMatthew G. Knepley 36449f4ada15SMatthew G. Knepley Level: beginner 36459f4ada15SMatthew G. Knepley 36469f4ada15SMatthew G. Knepley Notes: 36479f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 36489f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 364920f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 36509f4ada15SMatthew G. Knepley with the identity. 36519f4ada15SMatthew G. Knepley 36522c9a7b26SBarry Smith You must also call `DMPlexRestoreOrientedCone()` after you finish using the returned array. 36532c9a7b26SBarry Smith 36549f4ada15SMatthew G. Knepley Fortran Notes: 36552c9a7b26SBarry Smith `cone` and `ornt` must be declared with 36562c9a7b26SBarry Smith .vb 36572c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 36582c9a7b26SBarry Smith PetscInt, pointer :: ornt(:) 36592c9a7b26SBarry Smith .ve 36609f4ada15SMatthew G. Knepley 36611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 36629f4ada15SMatthew G. Knepley @*/ 3663ce78bad3SBarry Smith PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, PeOp const PetscInt *cone[], PeOp const PetscInt *ornt[]) 36649f4ada15SMatthew G. Knepley { 36659f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 36669f4ada15SMatthew G. Knepley 36679f4ada15SMatthew G. Knepley PetscFunctionBegin; 36689f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36699f4ada15SMatthew G. Knepley if (mesh->tr) { 36709f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 36719f4ada15SMatthew G. Knepley } else { 36729f4ada15SMatthew G. Knepley PetscInt off; 36739f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 36749f4ada15SMatthew G. Knepley PetscInt dof; 36759f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 36769f4ada15SMatthew G. Knepley if (dof) { 36774f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 36784f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 36799f4ada15SMatthew G. Knepley } 36809f4ada15SMatthew G. Knepley } 36819f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 36828e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 36838e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 36849f4ada15SMatthew G. Knepley } 36853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36869f4ada15SMatthew G. Knepley } 36879f4ada15SMatthew G. Knepley 36889f4ada15SMatthew G. Knepley /*@C 36892c9a7b26SBarry Smith DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG obtained with `DMPlexGetOrientedCone()` 36909f4ada15SMatthew G. Knepley 369120f4b53cSBarry Smith Not Collective 36929f4ada15SMatthew G. Knepley 36939f4ada15SMatthew G. Knepley Input Parameters: 36949f4ada15SMatthew G. Knepley + dm - The DMPlex 369520f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36969f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 369720f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 36989f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 36999f4ada15SMatthew G. Knepley 37009f4ada15SMatthew G. Knepley Level: beginner 37019f4ada15SMatthew G. Knepley 37021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 37039f4ada15SMatthew G. Knepley @*/ 37049f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 37059f4ada15SMatthew G. Knepley { 37069f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37079f4ada15SMatthew G. Knepley 37089f4ada15SMatthew G. Knepley PetscFunctionBegin; 37099f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37109f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 37113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37129f4ada15SMatthew G. Knepley } 37139f4ada15SMatthew G. Knepley 3714552f7358SJed Brown /*@ 3715eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3716552f7358SJed Brown 3717a1cb98faSBarry Smith Not Collective 3718552f7358SJed Brown 3719552f7358SJed Brown Input Parameters: 372060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3721a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3722552f7358SJed Brown 3723552f7358SJed Brown Output Parameter: 372420f4b53cSBarry Smith . size - The support size for point `p` 3725552f7358SJed Brown 3726552f7358SJed Brown Level: beginner 3727552f7358SJed Brown 37281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3729552f7358SJed Brown @*/ 3730d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3731d71ae5a4SJacob Faibussowitsch { 3732552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3733552f7358SJed Brown 3734552f7358SJed Brown PetscFunctionBegin; 3735552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37364f572ea9SToby Isaac PetscAssertPointer(size, 3); 37379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 37383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3739552f7358SJed Brown } 3740552f7358SJed Brown 3741552f7358SJed Brown /*@ 3742eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3743552f7358SJed Brown 3744a1cb98faSBarry Smith Not Collective 3745552f7358SJed Brown 3746552f7358SJed Brown Input Parameters: 374760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3748a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 374920f4b53cSBarry Smith - size - The support size for point `p` 3750552f7358SJed Brown 3751a1cb98faSBarry Smith Level: beginner 3752552f7358SJed Brown 3753552f7358SJed Brown Note: 375420f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3755552f7358SJed Brown 37561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3757552f7358SJed Brown @*/ 3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3759d71ae5a4SJacob Faibussowitsch { 3760552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3761552f7358SJed Brown 3762552f7358SJed Brown PetscFunctionBegin; 3763552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 37653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3766552f7358SJed Brown } 3767552f7358SJed Brown 3768552f7358SJed Brown /*@C 3769eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3770552f7358SJed Brown 3771a1cb98faSBarry Smith Not Collective 3772552f7358SJed Brown 3773552f7358SJed Brown Input Parameters: 377460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3775a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3776552f7358SJed Brown 3777552f7358SJed Brown Output Parameter: 37782c9a7b26SBarry Smith . support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3779552f7358SJed Brown 3780552f7358SJed Brown Level: beginner 3781552f7358SJed Brown 378260225df5SJacob Faibussowitsch Fortran Notes: 37832c9a7b26SBarry Smith `support` must be declared with 37842c9a7b26SBarry Smith .vb 37852c9a7b26SBarry Smith PetscInt, pointer :: support(:) 37862c9a7b26SBarry Smith .ve 37872c9a7b26SBarry Smith 3788a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3789a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 37903813dfbdSMatthew G Knepley 37911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3792552f7358SJed Brown @*/ 3793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3794d71ae5a4SJacob Faibussowitsch { 3795552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3796552f7358SJed Brown PetscInt off; 3797552f7358SJed Brown 3798552f7358SJed Brown PetscFunctionBegin; 3799552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38004f572ea9SToby Isaac PetscAssertPointer(support, 3); 38019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 38028e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 38033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3804552f7358SJed Brown } 3805552f7358SJed Brown 3806552f7358SJed Brown /*@ 380792371b87SBarry 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 3808552f7358SJed Brown 3809a1cb98faSBarry Smith Not Collective 3810552f7358SJed Brown 3811552f7358SJed Brown Input Parameters: 381260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3813a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 38142c9a7b26SBarry Smith - support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3815552f7358SJed Brown 3816552f7358SJed Brown Level: beginner 3817552f7358SJed Brown 3818a1cb98faSBarry Smith Note: 3819a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3820a1cb98faSBarry Smith 38211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3822552f7358SJed Brown @*/ 3823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3824d71ae5a4SJacob Faibussowitsch { 3825552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3826552f7358SJed Brown PetscInt pStart, pEnd; 3827552f7358SJed Brown PetscInt dof, off, c; 3828552f7358SJed Brown 3829552f7358SJed Brown PetscFunctionBegin; 3830552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 38329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 38334f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 38349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 383563a3b9bcSJacob 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); 3836552f7358SJed Brown for (c = 0; c < dof; ++c) { 383763a3b9bcSJacob 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); 3838552f7358SJed Brown mesh->supports[off + c] = support[c]; 3839552f7358SJed Brown } 38403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3841552f7358SJed Brown } 3842552f7358SJed Brown 38437cd05799SMatthew G. Knepley /*@ 3844eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 38457cd05799SMatthew G. Knepley 3846a1cb98faSBarry Smith Not Collective 38477cd05799SMatthew G. Knepley 38487cd05799SMatthew G. Knepley Input Parameters: 384960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3850a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 38517cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 38527cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 38537cd05799SMatthew G. Knepley 38547cd05799SMatthew G. Knepley Level: beginner 38557cd05799SMatthew G. Knepley 38561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 38577cd05799SMatthew G. Knepley @*/ 3858d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3859d71ae5a4SJacob Faibussowitsch { 3860552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3861552f7358SJed Brown PetscInt pStart, pEnd; 3862552f7358SJed Brown PetscInt dof, off; 3863552f7358SJed Brown 3864552f7358SJed Brown PetscFunctionBegin; 3865552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 38679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 38689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 386963a3b9bcSJacob 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); 387063a3b9bcSJacob 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); 387163a3b9bcSJacob 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); 3872552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 38733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3874552f7358SJed Brown } 3875552f7358SJed Brown 3876b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3877d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3878d71ae5a4SJacob Faibussowitsch { 3879b5a892a1SMatthew G. Knepley switch (ct) { 3880b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3881b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3882b5a892a1SMatthew G. Knepley break; 3883b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3884b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3885b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3886b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3887b5a892a1SMatthew G. Knepley break; 3888b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3889b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3890b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3891b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3892b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3893b5a892a1SMatthew G. Knepley break; 3894d71ae5a4SJacob Faibussowitsch default: 3895d71ae5a4SJacob Faibussowitsch return o; 3896b5a892a1SMatthew G. Knepley } 3897b5a892a1SMatthew G. Knepley return o; 3898b5a892a1SMatthew G. Knepley } 3899b5a892a1SMatthew G. Knepley 3900b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3901d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3902d71ae5a4SJacob Faibussowitsch { 3903b5a892a1SMatthew G. Knepley switch (ct) { 3904b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3905b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3906b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3907b5a892a1SMatthew G. Knepley break; 3908b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3909b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3910b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3911b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3912b5a892a1SMatthew G. Knepley break; 3913b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3914b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3915b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3916b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3917b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3918b5a892a1SMatthew G. Knepley break; 3919d71ae5a4SJacob Faibussowitsch default: 3920d71ae5a4SJacob Faibussowitsch return o; 3921b5a892a1SMatthew G. Knepley } 3922b5a892a1SMatthew G. Knepley return o; 3923b5a892a1SMatthew G. Knepley } 3924b5a892a1SMatthew G. Knepley 3925b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3927d71ae5a4SJacob Faibussowitsch { 3928b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3929b5a892a1SMatthew G. Knepley 3930b5a892a1SMatthew G. Knepley PetscFunctionBegin; 39319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3932b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3933b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3934b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3935b5a892a1SMatthew G. Knepley 39369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 39389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3939b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3940b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3941b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3942b5a892a1SMatthew G. Knepley 39439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3944b5a892a1SMatthew G. Knepley switch (ct) { 3945b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 39469566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39479566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3948b5a892a1SMatthew G. Knepley break; 3949b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 39509566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 39519566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39529566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3953b5a892a1SMatthew G. Knepley break; 3954b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 39559566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 39569566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39579566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 39589566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3959b5a892a1SMatthew G. Knepley break; 3960d71ae5a4SJacob Faibussowitsch default: 3961d71ae5a4SJacob Faibussowitsch break; 3962b5a892a1SMatthew G. Knepley } 3963b5a892a1SMatthew G. Knepley } 3964b5a892a1SMatthew G. Knepley } 39653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3966b5a892a1SMatthew G. Knepley } 3967b5a892a1SMatthew G. Knepley 396809015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 396909015e70SStefano Zampini { 397009015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 397109015e70SStefano Zampini 397209015e70SStefano Zampini PetscFunctionBeginHot; 397309015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 397409015e70SStefano Zampini if (useCone) { 397509015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 397609015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 397709015e70SStefano Zampini } else { 397809015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 397909015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 398009015e70SStefano Zampini } 398109015e70SStefano Zampini } else { 398209015e70SStefano Zampini if (useCone) { 398309015e70SStefano Zampini const PetscSection s = mesh->coneSection; 398409015e70SStefano Zampini const PetscInt ps = p - s->pStart; 398509015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 398609015e70SStefano Zampini 398709015e70SStefano Zampini *size = s->atlasDof[ps]; 398809015e70SStefano Zampini *arr = mesh->cones + off; 398909015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 399009015e70SStefano Zampini } else { 399109015e70SStefano Zampini const PetscSection s = mesh->supportSection; 399209015e70SStefano Zampini const PetscInt ps = p - s->pStart; 399309015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 399409015e70SStefano Zampini 399509015e70SStefano Zampini *size = s->atlasDof[ps]; 399609015e70SStefano Zampini *arr = mesh->supports + off; 399709015e70SStefano Zampini } 399809015e70SStefano Zampini } 399909015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 400009015e70SStefano Zampini } 400109015e70SStefano Zampini 400209015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 400309015e70SStefano Zampini { 400409015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 400509015e70SStefano Zampini 400609015e70SStefano Zampini PetscFunctionBeginHot; 400709015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 400809015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 400909015e70SStefano Zampini } 401009015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 401109015e70SStefano Zampini } 401209015e70SStefano Zampini 4013d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4014d71ae5a4SJacob Faibussowitsch { 4015b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4016b5a892a1SMatthew G. Knepley PetscInt *closure; 4017b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 4018b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 4019b5a892a1SMatthew G. Knepley 4020b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4021b5a892a1SMatthew G. Knepley if (ornt) { 40229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4023476787b7SMatthew 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; 4024b5a892a1SMatthew G. Knepley } 4025b5a892a1SMatthew G. Knepley if (*points) { 4026b5a892a1SMatthew G. Knepley closure = *points; 4027b5a892a1SMatthew G. Knepley } else { 4028b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 40299566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 40309566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 4031b5a892a1SMatthew G. Knepley } 403209015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 4033b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 4034b5a892a1SMatthew G. Knepley closure[off++] = p; 4035b5a892a1SMatthew G. Knepley closure[off++] = 0; 4036b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4037b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 4038b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 4039b5a892a1SMatthew G. Knepley } 4040b5a892a1SMatthew G. Knepley } else { 404185036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 4042b5a892a1SMatthew G. Knepley 4043b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 4044b5a892a1SMatthew G. Knepley closure[off++] = p; 4045b5a892a1SMatthew G. Knepley closure[off++] = ornt; 4046b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4047b5a892a1SMatthew G. Knepley DMPolytopeType ft; 4048b5a892a1SMatthew G. Knepley 40499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 4050b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 4051b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 4052b5a892a1SMatthew G. Knepley } 4053b5a892a1SMatthew G. Knepley } 405409015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 4055b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 4056b5a892a1SMatthew G. Knepley if (points) *points = closure; 40573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4058b5a892a1SMatthew G. Knepley } 4059b5a892a1SMatthew G. Knepley 4060d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 4061d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 4062d71ae5a4SJacob Faibussowitsch { 406385036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 4064b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 4065b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 4066b5a892a1SMatthew G. Knepley DMPolytopeType ft; 4067b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 4068b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 4069b5a892a1SMatthew G. Knepley 4070b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 40719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 407209015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 40739566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4074b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 4075b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 4076b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 40779371c9d4SSatish Balay if (*points) { 40789371c9d4SSatish Balay pts = *points; 40799371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 4080b5a892a1SMatthew G. Knepley c = 0; 4081b5a892a1SMatthew G. Knepley pts[c++] = point; 4082b5a892a1SMatthew G. Knepley pts[c++] = o; 40839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 40849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 40859371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40869371c9d4SSatish Balay pts[c++] = closure[cl]; 40879371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40889371c9d4SSatish Balay } 40899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 40909371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40919371c9d4SSatish Balay pts[c++] = closure[cl]; 40929371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40939371c9d4SSatish Balay } 40949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 4095b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 40969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 4097b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 4098b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 4099b5a892a1SMatthew G. Knepley } 410009015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 4101b5a892a1SMatthew G. Knepley if (dim >= 3) { 4102b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 4103b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 4104b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 4105b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 4106b5a892a1SMatthew G. Knepley 41079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 410885036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 410909015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4110b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 4111b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 4112b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 4113b5a892a1SMatthew G. Knepley 41149371c9d4SSatish Balay for (i = 0; i < c; i += 2) 41159371c9d4SSatish Balay if (pts[i] == cp) break; 4116b5a892a1SMatthew G. Knepley if (i == c) { 41179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 4118b5a892a1SMatthew G. Knepley pts[c++] = cp; 4119b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 4120b5a892a1SMatthew G. Knepley } 4121b5a892a1SMatthew G. Knepley } 412209015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4123b5a892a1SMatthew G. Knepley } 4124b5a892a1SMatthew G. Knepley } 4125b5a892a1SMatthew G. Knepley *numPoints = c / 2; 4126b5a892a1SMatthew G. Knepley *points = pts; 41273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4128b5a892a1SMatthew G. Knepley } 4129b5a892a1SMatthew G. Knepley 4130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4131d71ae5a4SJacob Faibussowitsch { 4132b5a892a1SMatthew G. Knepley DMPolytopeType ct; 4133b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 4134b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 4135b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 4136b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 4137b5a892a1SMatthew G. Knepley 4138b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 41399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4140b5a892a1SMatthew G. Knepley if (depth == 1) { 41419566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 41423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4143b5a892a1SMatthew G. Knepley } 41449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4145476787b7SMatthew 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; 4146c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 41479566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 41483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4149b5a892a1SMatthew G. Knepley } 41509566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4151b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 4152b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 4153b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 41549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 41559371c9d4SSatish Balay if (*points) { 41569371c9d4SSatish Balay closure = *points; 41579371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 4158b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 4159b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 4160b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 4161b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 4162b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4163b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 4164b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 4165b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 4166b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 4167b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 416885036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 416909015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4170b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4171b5a892a1SMatthew G. Knepley 4172b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 417385036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 417463a3b9bcSJacob 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); 4175b5a892a1SMatthew G. Knepley } 417609015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4177b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4178b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4179b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4180b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 41819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4182b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4183b5a892a1SMatthew G. Knepley PetscInt c; 4184b5a892a1SMatthew G. Knepley 4185b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4186b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4187b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4188b5a892a1SMatthew G. Knepley } 4189b5a892a1SMatthew G. Knepley if (c == closureSize) { 4190b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4191b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4192b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4193b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4194b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4195b5a892a1SMatthew G. Knepley } 4196b5a892a1SMatthew G. Knepley } 419709015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4198b5a892a1SMatthew G. Knepley } 41999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4200b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4201b5a892a1SMatthew G. Knepley if (points) *points = closure; 42023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4203b5a892a1SMatthew G. Knepley } 4204b5a892a1SMatthew G. Knepley 4205552f7358SJed Brown /*@C 4206eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4207552f7358SJed Brown 4208a1cb98faSBarry Smith Not Collective 4209552f7358SJed Brown 4210552f7358SJed Brown Input Parameters: 4211a1cb98faSBarry Smith + dm - The `DMPLEX` 4212b5a892a1SMatthew G. Knepley . p - The mesh point 4213*7d8e5ce9SJames Wright - useCone - `PETSC_TRUE` for the closure, otherwise return the support 4214552f7358SJed Brown 42156b867d5aSJose E. Roman Input/Output Parameter: 42166b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 42172c9a7b26SBarry Smith if *points is `NULL` on input, internal storage will be returned, use `DMPlexRestoreTransitiveClosure()`, 42182c9a7b26SBarry Smith otherwise the provided array is used to hold the values 42196b867d5aSJose E. Roman 42206b867d5aSJose E. Roman Output Parameter: 42212c9a7b26SBarry Smith . numPoints - The number of points in the closure, so `points` is of size 2*`numPoints` 4222552f7358SJed Brown 4223a1cb98faSBarry Smith Level: beginner 4224a1cb98faSBarry Smith 4225552f7358SJed Brown Note: 422620f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4227552f7358SJed Brown 422860225df5SJacob Faibussowitsch Fortran Notes: 42292c9a7b26SBarry Smith `points` must be declared with 42302c9a7b26SBarry Smith .vb 42312c9a7b26SBarry Smith PetscInt, pointer :: points(:) 42322c9a7b26SBarry Smith .ve 42332c9a7b26SBarry Smith and is always allocated by the function. 42342c9a7b26SBarry Smith 4235feaf08eaSBarry Smith Pass `PETSC_NULL_INTEGER` for `numPoints` if it is not needed 42363813dfbdSMatthew G Knepley 42371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4238552f7358SJed Brown @*/ 4239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4240d71ae5a4SJacob Faibussowitsch { 4241b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4242552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42434f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 42444f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 4245332e0eaaSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 4246332e0eaaSMatthew G. Knepley PetscInt pStart, pEnd; 4247332e0eaaSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4248332e0eaaSMatthew G. Knepley PetscCheck(p >= pStart && p < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 4249332e0eaaSMatthew G. Knepley } 42509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 42513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42529bf0dad6SMatthew G. Knepley } 42539bf0dad6SMatthew G. Knepley 4254552f7358SJed Brown /*@C 4255eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4256552f7358SJed Brown 4257a1cb98faSBarry Smith Not Collective 4258552f7358SJed Brown 4259552f7358SJed Brown Input Parameters: 4260a1cb98faSBarry Smith + dm - The `DMPLEX` 4261b5a892a1SMatthew G. Knepley . p - The mesh point 4262a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 426320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4264b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4265552f7358SJed Brown 4266a1cb98faSBarry Smith Level: beginner 4267a1cb98faSBarry Smith 4268552f7358SJed Brown Note: 426920f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4270552f7358SJed Brown 42711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4272552f7358SJed Brown @*/ 4273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4274d71ae5a4SJacob Faibussowitsch { 4275b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4276552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42774ff43b2cSJed Brown if (numPoints) *numPoints = 0; 42789566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 42793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4280552f7358SJed Brown } 4281552f7358SJed Brown 4282552f7358SJed Brown /*@ 4283eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4284552f7358SJed Brown 4285a1cb98faSBarry Smith Not Collective 4286552f7358SJed Brown 4287552f7358SJed Brown Input Parameter: 428860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4289552f7358SJed Brown 4290552f7358SJed Brown Output Parameters: 4291552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4292552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4293552f7358SJed Brown 4294552f7358SJed Brown Level: beginner 4295552f7358SJed Brown 42961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4297552f7358SJed Brown @*/ 4298ce78bad3SBarry Smith PetscErrorCode DMPlexGetMaxSizes(DM dm, PeOp PetscInt *maxConeSize, PeOp PetscInt *maxSupportSize) 4299d71ae5a4SJacob Faibussowitsch { 4300552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4301552f7358SJed Brown 4302552f7358SJed Brown PetscFunctionBegin; 4303552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43041baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 43051baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 43063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4307552f7358SJed Brown } 4308552f7358SJed Brown 4309d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4310d71ae5a4SJacob Faibussowitsch { 4311552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 43126302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4313552f7358SJed Brown 4314552f7358SJed Brown PetscFunctionBegin; 4315552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 43179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 43189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 43199566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 43206302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 43216302a7fbSVaclav Hapla if (maxSupportSize) { 43229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 43239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 43249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4325552f7358SJed Brown } 43263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4327552f7358SJed Brown } 4328552f7358SJed Brown 4329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4330d71ae5a4SJacob Faibussowitsch { 4331552f7358SJed Brown PetscFunctionBegin; 43329566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4333dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4334ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4335736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 433695602cf2SAlexis Marboeuf PetscSF sfNatural; 4337f94b4a02SBlaise Bourdin 43383dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 43399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 434095602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4341c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4342f94b4a02SBlaise Bourdin } 43433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4344552f7358SJed Brown } 4345552f7358SJed Brown 4346d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4347d71ae5a4SJacob Faibussowitsch { 43483dcd263cSBlaise Bourdin PetscInt i = 0; 43492adcc780SMatthew G. Knepley 43502adcc780SMatthew G. Knepley PetscFunctionBegin; 43519566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 43529566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4353c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 43543dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 43553dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 435695602cf2SAlexis Marboeuf PetscSF sfNatural; 43573dcd263cSBlaise Bourdin 43583dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 43599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4360c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 436195602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4362c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 43633dcd263cSBlaise Bourdin break; 43643dcd263cSBlaise Bourdin } 43653dcd263cSBlaise Bourdin } 43663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43672adcc780SMatthew G. Knepley } 43682adcc780SMatthew G. Knepley 4369552f7358SJed Brown /*@ 4370eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4371552f7358SJed Brown 4372a1cb98faSBarry Smith Not Collective 4373552f7358SJed Brown 4374552f7358SJed Brown Input Parameter: 437560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4376552f7358SJed Brown 4377552f7358SJed Brown Level: beginner 4378552f7358SJed Brown 4379a1cb98faSBarry Smith Note: 4380a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4381a1cb98faSBarry Smith 43821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4383552f7358SJed Brown @*/ 4384d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4385d71ae5a4SJacob Faibussowitsch { 4386552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4387552f7358SJed Brown PetscInt *offsets; 4388552f7358SJed Brown PetscInt supportSize; 4389552f7358SJed Brown PetscInt pStart, pEnd, p; 4390552f7358SJed Brown 4391552f7358SJed Brown PetscFunctionBegin; 4392552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 439328b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 43949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4395552f7358SJed Brown /* Calculate support sizes */ 43969566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4397552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4398552f7358SJed Brown PetscInt dof, off, c; 4399552f7358SJed Brown 44009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 44019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 440248a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4403552f7358SJed Brown } 44049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4405552f7358SJed Brown /* Calculate supports */ 44069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 44079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 44089566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4409552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4410552f7358SJed Brown PetscInt dof, off, c; 4411552f7358SJed Brown 44129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 44139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4414552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4415552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4416552f7358SJed Brown PetscInt offS; 4417552f7358SJed Brown 44189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 44190d644c17SKarl Rupp 4420552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4421552f7358SJed Brown ++offsets[q]; 4422552f7358SJed Brown } 4423552f7358SJed Brown } 44249566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 44259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 44263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4427552f7358SJed Brown } 4428552f7358SJed Brown 4429d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4430d71ae5a4SJacob Faibussowitsch { 4431277ea44aSLisandro Dalcin IS stratumIS; 4432277ea44aSLisandro Dalcin 4433277ea44aSLisandro Dalcin PetscFunctionBegin; 44343ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 443576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4436277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4437277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 44389566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4439277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 44409566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 44419371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 44429371c9d4SSatish Balay overlap = PETSC_TRUE; 44439371c9d4SSatish Balay break; 44449371c9d4SSatish Balay } 4445277ea44aSLisandro Dalcin } 444663a3b9bcSJacob 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); 4447277ea44aSLisandro Dalcin } 44489566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 44499566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 44509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 44513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4452277ea44aSLisandro Dalcin } 4453277ea44aSLisandro Dalcin 4454e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4455e91fa0a1SMatthew G. Knepley { 4456e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4457e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 44581690c2aeSBarry Smith PetscInt dmin = PETSC_INT_MAX, dmax = PETSC_INT_MIN; 4459e91fa0a1SMatthew G. Knepley 4460e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4461e91fa0a1SMatthew G. Knepley { 4462e91fa0a1SMatthew G. Knepley DMLabel label2; 4463e91fa0a1SMatthew G. Knepley 4464e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4465e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4466e91fa0a1SMatthew G. Knepley } 4467e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4468e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4469e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4470e91fa0a1SMatthew G. Knepley 4471e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4472e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4473e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4474e91fa0a1SMatthew G. Knepley } 4475e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4476e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 44771690c2aeSBarry Smith pMin[d] = PETSC_INT_MAX; 44781690c2aeSBarry Smith pMax[d] = PETSC_INT_MIN; 4479e91fa0a1SMatthew G. Knepley } 4480e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4481e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4482e91fa0a1SMatthew G. Knepley PetscInt d; 4483e91fa0a1SMatthew G. Knepley 4484e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4485e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4486e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4487e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4488e91fa0a1SMatthew G. Knepley } 4489e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4490e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4491e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4492e91fa0a1SMatthew G. Knepley } 4493e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4494e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4495e91fa0a1SMatthew G. Knepley } 4496e91fa0a1SMatthew G. Knepley 4497e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4498e91fa0a1SMatthew G. Knepley { 4499e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4500e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4501e91fa0a1SMatthew G. Knepley 4502e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4503e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4504e91fa0a1SMatthew G. Knepley { 4505e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 45061690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45071690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4508e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4509e91fa0a1SMatthew G. Knepley 4510e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4511e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4512e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4513e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4514e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4515e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4516e91fa0a1SMatthew G. Knepley ++numRoots; 4517e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4518e91fa0a1SMatthew G. Knepley ++numLeaves; 4519e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4520e91fa0a1SMatthew G. Knepley /* Isolated points */ 4521e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4522e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4523e91fa0a1SMatthew G. Knepley } 4524e91fa0a1SMatthew G. Knepley } 4525e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4526e91fa0a1SMatthew G. Knepley } 4527e91fa0a1SMatthew G. Knepley 4528e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 45291690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45301690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4531e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4532e91fa0a1SMatthew G. Knepley 4533e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4534e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4535e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4536e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4537e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4538e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4539e91fa0a1SMatthew G. Knepley } 4540e91fa0a1SMatthew G. Knepley } 4541e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4542e91fa0a1SMatthew G. Knepley } else { 4543e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4544e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4545e91fa0a1SMatthew G. Knepley 4546e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4547e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 45481690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45491690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4550e91fa0a1SMatthew G. Knepley 4551e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4552e91fa0a1SMatthew G. Knepley const PetscInt *support; 4553e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4554e91fa0a1SMatthew G. Knepley 4555e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4556e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4557e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4558e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4559e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4560e91fa0a1SMatthew G. Knepley } 4561e91fa0a1SMatthew G. Knepley } 4562e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4563e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4564e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4565e91fa0a1SMatthew G. Knepley } 4566e91fa0a1SMatthew G. Knepley } 4567e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4568e91fa0a1SMatthew G. Knepley } 4569e91fa0a1SMatthew G. Knepley 4570552f7358SJed Brown /*@ 4571a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4572552f7358SJed Brown 457320f4b53cSBarry Smith Collective 4574552f7358SJed Brown 4575552f7358SJed Brown Input Parameter: 457660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4577552f7358SJed Brown 4578a1cb98faSBarry Smith Level: beginner 4579552f7358SJed Brown 4580552f7358SJed Brown Notes: 4581a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4582a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4583a4e35b19SJacob Faibussowitsch 4584a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4585a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4586a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4587b1bb481bSMatthew 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 4588a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4589a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4590a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4591552f7358SJed Brown 4592b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4593b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4594b1bb481bSMatthew 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 4595b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4596a1cb98faSBarry Smith .vb 4597a1cb98faSBarry Smith cone(c0) = {e0, v2} 4598a1cb98faSBarry Smith cone(e0) = {v0, v1} 4599a1cb98faSBarry Smith .ve 4600a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4601a1cb98faSBarry Smith .vb 4602a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4603a1cb98faSBarry Smith depth 1 = {e0, c0} 4604a1cb98faSBarry Smith .ve 4605b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4606b1bb481bSMatthew Knepley 4607a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4608552f7358SJed Brown 46091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4610552f7358SJed Brown @*/ 4611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4612d71ae5a4SJacob Faibussowitsch { 4613df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4614aa50250dSMatthew G. Knepley DMLabel label; 4615e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4616552f7358SJed Brown 4617552f7358SJed Brown PetscFunctionBegin; 4618552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46199566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4620277ea44aSLisandro Dalcin 4621e91fa0a1SMatthew G. Knepley // Create depth label 4622d28dd301SMatthew G. Knepley PetscCall(DMRemoveLabel(dm, "depth", NULL)); 46239566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4625277ea44aSLisandro Dalcin 4626e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4627e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4628e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4629552f7358SJed Brown 4630bf4602e4SToby Isaac { /* just in case there is an empty process */ 4631bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4632bf4602e4SToby Isaac 46339566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4634462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 463548a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4636bf4602e4SToby Isaac } 46379566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 46389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 46393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4640552f7358SJed Brown } 4641552f7358SJed Brown 4642d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4643d71ae5a4SJacob Faibussowitsch { 4644412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4645412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 46465e2c5519SMatthew G. Knepley PetscBool preferTensor; 4647ba2698f1SMatthew G. Knepley 4648412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 46499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 46509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 46519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 46525e2c5519SMatthew G. Knepley PetscCall(DMPlexGetInterpolatePreferTensor(dm, &preferTensor)); 4653ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4654ba2698f1SMatthew G. Knepley if (depth <= 1) { 4655ba2698f1SMatthew G. Knepley switch (pdepth) { 4656d71ae5a4SJacob Faibussowitsch case 0: 4657d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4658d71ae5a4SJacob Faibussowitsch break; 4659ba2698f1SMatthew G. Knepley case 1: 4660ba2698f1SMatthew G. Knepley switch (coneSize) { 4661d71ae5a4SJacob Faibussowitsch case 2: 4662d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4663d71ae5a4SJacob Faibussowitsch break; 4664d71ae5a4SJacob Faibussowitsch case 3: 4665d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4666d71ae5a4SJacob Faibussowitsch break; 4667ba2698f1SMatthew G. Knepley case 4: 4668ba2698f1SMatthew G. Knepley switch (dim) { 4669d71ae5a4SJacob Faibussowitsch case 2: 4670d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4671d71ae5a4SJacob Faibussowitsch break; 4672d71ae5a4SJacob Faibussowitsch case 3: 4673d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4674d71ae5a4SJacob Faibussowitsch break; 4675d71ae5a4SJacob Faibussowitsch default: 4676d71ae5a4SJacob Faibussowitsch break; 4677ba2698f1SMatthew G. Knepley } 4678ba2698f1SMatthew G. Knepley break; 4679d71ae5a4SJacob Faibussowitsch case 5: 4680d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4681d71ae5a4SJacob Faibussowitsch break; 4682d71ae5a4SJacob Faibussowitsch case 6: 46835e2c5519SMatthew G. Knepley ct = preferTensor ? DM_POLYTOPE_TRI_PRISM_TENSOR : DM_POLYTOPE_TRI_PRISM; 4684d71ae5a4SJacob Faibussowitsch break; 4685d71ae5a4SJacob Faibussowitsch case 8: 4686d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4687d71ae5a4SJacob Faibussowitsch break; 4688d71ae5a4SJacob Faibussowitsch default: 4689d71ae5a4SJacob Faibussowitsch break; 4690ba2698f1SMatthew G. Knepley } 4691ba2698f1SMatthew G. Knepley } 4692ba2698f1SMatthew G. Knepley } else { 4693ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4694ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4695ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4696ba2698f1SMatthew G. Knepley switch (dim) { 4697ba2698f1SMatthew G. Knepley case 1: 4698ba2698f1SMatthew G. Knepley switch (coneSize) { 4699d71ae5a4SJacob Faibussowitsch case 2: 4700d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4701d71ae5a4SJacob Faibussowitsch break; 4702d71ae5a4SJacob Faibussowitsch default: 4703d71ae5a4SJacob Faibussowitsch break; 4704ba2698f1SMatthew G. Knepley } 4705ba2698f1SMatthew G. Knepley break; 4706ba2698f1SMatthew G. Knepley case 2: 4707ba2698f1SMatthew G. Knepley switch (coneSize) { 4708d71ae5a4SJacob Faibussowitsch case 3: 4709d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4710d71ae5a4SJacob Faibussowitsch break; 4711d71ae5a4SJacob Faibussowitsch case 4: 4712d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4713d71ae5a4SJacob Faibussowitsch break; 4714d71ae5a4SJacob Faibussowitsch default: 4715d71ae5a4SJacob Faibussowitsch break; 4716ba2698f1SMatthew G. Knepley } 4717ba2698f1SMatthew G. Knepley break; 4718ba2698f1SMatthew G. Knepley case 3: 4719ba2698f1SMatthew G. Knepley switch (coneSize) { 4720d71ae5a4SJacob Faibussowitsch case 4: 4721d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4722d71ae5a4SJacob Faibussowitsch break; 47239371c9d4SSatish Balay case 5: { 4724da9060c4SMatthew G. Knepley const PetscInt *cone; 4725da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4726da9060c4SMatthew G. Knepley 47279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 47289566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4729da9060c4SMatthew G. Knepley switch (faceConeSize) { 4730d71ae5a4SJacob Faibussowitsch case 3: 47315e2c5519SMatthew G. Knepley ct = preferTensor ? DM_POLYTOPE_TRI_PRISM_TENSOR : DM_POLYTOPE_TRI_PRISM; 4732d71ae5a4SJacob Faibussowitsch break; 4733d71ae5a4SJacob Faibussowitsch case 4: 4734d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4735d71ae5a4SJacob Faibussowitsch break; 4736da9060c4SMatthew G. Knepley } 47379371c9d4SSatish Balay } break; 4738d71ae5a4SJacob Faibussowitsch case 6: 4739d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4740d71ae5a4SJacob Faibussowitsch break; 4741d71ae5a4SJacob Faibussowitsch default: 4742d71ae5a4SJacob Faibussowitsch break; 4743ba2698f1SMatthew G. Knepley } 4744ba2698f1SMatthew G. Knepley break; 4745d71ae5a4SJacob Faibussowitsch default: 4746d71ae5a4SJacob Faibussowitsch break; 4747ba2698f1SMatthew G. Knepley } 4748ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4749ba2698f1SMatthew G. Knepley switch (coneSize) { 4750d71ae5a4SJacob Faibussowitsch case 2: 4751d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4752d71ae5a4SJacob Faibussowitsch break; 4753d71ae5a4SJacob Faibussowitsch case 3: 4754d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4755d71ae5a4SJacob Faibussowitsch break; 4756d71ae5a4SJacob Faibussowitsch case 4: 4757d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4758d71ae5a4SJacob Faibussowitsch break; 4759d71ae5a4SJacob Faibussowitsch default: 4760d71ae5a4SJacob Faibussowitsch break; 4761ba2698f1SMatthew G. Knepley } 4762ba2698f1SMatthew G. Knepley } 4763ba2698f1SMatthew G. Knepley } 4764412e9a14SMatthew G. Knepley *pt = ct; 47653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4766ba2698f1SMatthew G. Knepley } 4767412e9a14SMatthew G. Knepley 4768412e9a14SMatthew G. Knepley /*@ 4769412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4770412e9a14SMatthew G. Knepley 477120f4b53cSBarry Smith Collective 4772412e9a14SMatthew G. Knepley 4773412e9a14SMatthew G. Knepley Input Parameter: 477460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4775412e9a14SMatthew G. Knepley 4776412e9a14SMatthew G. Knepley Level: developer 4777412e9a14SMatthew G. Knepley 4778a1cb98faSBarry Smith Note: 4779a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4780a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4781a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4782412e9a14SMatthew G. Knepley 4783a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4784a1cb98faSBarry Smith 47851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4786412e9a14SMatthew G. Knepley @*/ 4787d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4788d71ae5a4SJacob Faibussowitsch { 4789412e9a14SMatthew G. Knepley DM_Plex *mesh; 4790412e9a14SMatthew G. Knepley DMLabel ctLabel; 4791412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4792412e9a14SMatthew G. Knepley 4793412e9a14SMatthew G. Knepley PetscFunctionBegin; 4794412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4795412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 47969566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 47979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 47989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 479921027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 480021027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4801412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4802327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4803412e9a14SMatthew G. Knepley PetscInt pdepth; 4804412e9a14SMatthew G. Knepley 48059566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 48069566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4807841fc1b7SMatthew 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 " has invalid celltype (%s)", p, DMPolytopeTypes[ct]); 48089566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 48096497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 4810412e9a14SMatthew G. Knepley } 48119566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 48129566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 48133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4814ba2698f1SMatthew G. Knepley } 4815ba2698f1SMatthew G. Knepley 4816552f7358SJed Brown /*@C 4817552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4818552f7358SJed Brown 4819552f7358SJed Brown Not Collective 4820552f7358SJed Brown 4821552f7358SJed Brown Input Parameters: 4822a1cb98faSBarry Smith + dm - The `DMPLEX` object 4823552f7358SJed Brown . numPoints - The number of input points for the join 4824552f7358SJed Brown - points - The input points 4825552f7358SJed Brown 4826552f7358SJed Brown Output Parameters: 4827552f7358SJed Brown + numCoveredPoints - The number of points in the join 4828552f7358SJed Brown - coveredPoints - The points in the join 4829552f7358SJed Brown 4830552f7358SJed Brown Level: intermediate 4831552f7358SJed Brown 4832a1cb98faSBarry Smith Note: 4833a1cb98faSBarry Smith Currently, this is restricted to a single level join 4834552f7358SJed Brown 483560225df5SJacob Faibussowitsch Fortran Notes: 48362c9a7b26SBarry Smith `converedPoints` must be declared with 48372c9a7b26SBarry Smith .vb 48382c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 48392c9a7b26SBarry Smith .ve 48402c9a7b26SBarry Smith 48411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4842552f7358SJed Brown @*/ 48435d83a8b1SBarry Smith PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4844d71ae5a4SJacob Faibussowitsch { 4845552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4846552f7358SJed Brown PetscInt *join[2]; 4847552f7358SJed Brown PetscInt joinSize, i = 0; 4848552f7358SJed Brown PetscInt dof, off, p, c, m; 48496302a7fbSVaclav Hapla PetscInt maxSupportSize; 4850552f7358SJed Brown 4851552f7358SJed Brown PetscFunctionBegin; 4852552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48534f572ea9SToby Isaac PetscAssertPointer(points, 3); 48544f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 48554f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 48566302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 48576302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 48586302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4859552f7358SJed Brown /* Copy in support of first point */ 48609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 48619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4862ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4863552f7358SJed Brown /* Check each successive support */ 4864552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4865552f7358SJed Brown PetscInt newJoinSize = 0; 4866552f7358SJed Brown 48679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 48689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4869552f7358SJed Brown for (c = 0; c < dof; ++c) { 4870552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4871552f7358SJed Brown 4872552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4873552f7358SJed Brown if (point == join[i][m]) { 4874552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4875552f7358SJed Brown break; 4876552f7358SJed Brown } 4877552f7358SJed Brown } 4878552f7358SJed Brown } 4879552f7358SJed Brown joinSize = newJoinSize; 4880552f7358SJed Brown i = 1 - i; 4881552f7358SJed Brown } 4882552f7358SJed Brown *numCoveredPoints = joinSize; 4883552f7358SJed Brown *coveredPoints = join[i]; 48846302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 48853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4886552f7358SJed Brown } 4887552f7358SJed Brown 4888552f7358SJed Brown /*@C 48892c9a7b26SBarry Smith DMPlexRestoreJoin - Restore an array for the join of the set of points obtained with `DMPlexGetJoin()` 4890552f7358SJed Brown 4891552f7358SJed Brown Not Collective 4892552f7358SJed Brown 4893552f7358SJed Brown Input Parameters: 4894a1cb98faSBarry Smith + dm - The `DMPLEX` object 4895552f7358SJed Brown . numPoints - The number of input points for the join 4896552f7358SJed Brown - points - The input points 4897552f7358SJed Brown 4898552f7358SJed Brown Output Parameters: 4899552f7358SJed Brown + numCoveredPoints - The number of points in the join 4900552f7358SJed Brown - coveredPoints - The points in the join 4901552f7358SJed Brown 4902552f7358SJed Brown Level: intermediate 4903552f7358SJed Brown 490460225df5SJacob Faibussowitsch Fortran Notes: 4905feaf08eaSBarry Smith `converedPoints` must be declared with 4906feaf08eaSBarry Smith .vb 4907feaf08eaSBarry Smith PetscInt, pointer :: coveredPoints(:) 4908feaf08eaSBarry Smith .ve 4909feaf08eaSBarry Smith 4910feaf08eaSBarry Smith Pass `PETSC_NULL_INTEGER` for `numCoveredPoints` if it is not needed 4911a1cb98faSBarry Smith 49121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4913552f7358SJed Brown @*/ 49142c9a7b26SBarry Smith PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4915d71ae5a4SJacob Faibussowitsch { 4916552f7358SJed Brown PetscFunctionBegin; 4917552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49184f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49194f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49204f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4922d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4924552f7358SJed Brown } 4925552f7358SJed Brown 4926552f7358SJed Brown /*@C 4927552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4928552f7358SJed Brown 4929552f7358SJed Brown Not Collective 4930552f7358SJed Brown 4931552f7358SJed Brown Input Parameters: 4932a1cb98faSBarry Smith + dm - The `DMPLEX` object 4933552f7358SJed Brown . numPoints - The number of input points for the join 49342c9a7b26SBarry Smith - points - The input points, its length is `numPoints` 4935552f7358SJed Brown 4936552f7358SJed Brown Output Parameters: 4937552f7358SJed Brown + numCoveredPoints - The number of points in the join 49382c9a7b26SBarry Smith - coveredPoints - The points in the join, its length is `numCoveredPoints` 4939552f7358SJed Brown 4940552f7358SJed Brown Level: intermediate 4941552f7358SJed Brown 494260225df5SJacob Faibussowitsch Fortran Notes: 49432c9a7b26SBarry Smith .vb 49442c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 49452c9a7b26SBarry Smith .ve 49462c9a7b26SBarry Smith 49471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4948552f7358SJed Brown @*/ 49495d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4950d71ae5a4SJacob Faibussowitsch { 4951552f7358SJed Brown PetscInt *offsets, **closures; 4952552f7358SJed Brown PetscInt *join[2]; 4953552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 495424c766afSToby Isaac PetscInt p, d, c, m, ms; 4955552f7358SJed Brown 4956552f7358SJed Brown PetscFunctionBegin; 4957552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49584f572ea9SToby Isaac PetscAssertPointer(points, 3); 49594f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49604f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4961552f7358SJed Brown 49629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 49639566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 49649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 49656302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 496624c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 49679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 49689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4969552f7358SJed Brown 4970552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4971552f7358SJed Brown PetscInt closureSize; 4972552f7358SJed Brown 49739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 49740d644c17SKarl Rupp 4975552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4976552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4977552f7358SJed Brown PetscInt pStart, pEnd, i; 4978552f7358SJed Brown 49799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4980552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4981552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4982552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4983552f7358SJed Brown break; 4984552f7358SJed Brown } 4985552f7358SJed Brown } 4986552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4987552f7358SJed Brown } 498863a3b9bcSJacob 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); 4989552f7358SJed Brown } 4990552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4991552f7358SJed Brown PetscInt dof; 4992552f7358SJed Brown 4993552f7358SJed Brown /* Copy in support of first point */ 4994552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4995ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4996552f7358SJed Brown /* Check each successive cone */ 4997552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4998552f7358SJed Brown PetscInt newJoinSize = 0; 4999552f7358SJed Brown 5000552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 5001552f7358SJed Brown for (c = 0; c < dof; ++c) { 5002552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 5003552f7358SJed Brown 5004552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 5005552f7358SJed Brown if (point == join[i][m]) { 5006552f7358SJed Brown join[1 - i][newJoinSize++] = point; 5007552f7358SJed Brown break; 5008552f7358SJed Brown } 5009552f7358SJed Brown } 5010552f7358SJed Brown } 5011552f7358SJed Brown joinSize = newJoinSize; 5012552f7358SJed Brown i = 1 - i; 5013552f7358SJed Brown } 5014552f7358SJed Brown if (joinSize) break; 5015552f7358SJed Brown } 5016552f7358SJed Brown *numCoveredPoints = joinSize; 5017552f7358SJed Brown *coveredPoints = join[i]; 501848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 50199566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 50216302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 50223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5023552f7358SJed Brown } 5024552f7358SJed Brown 5025552f7358SJed Brown /*@C 5026552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 5027552f7358SJed Brown 5028552f7358SJed Brown Not Collective 5029552f7358SJed Brown 5030552f7358SJed Brown Input Parameters: 5031a1cb98faSBarry Smith + dm - The `DMPLEX` object 5032552f7358SJed Brown . numPoints - The number of input points for the meet 50332c9a7b26SBarry Smith - points - The input points, of length `numPoints` 5034552f7358SJed Brown 5035552f7358SJed Brown Output Parameters: 503660225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 50372c9a7b26SBarry Smith - coveringPoints - The points in the meet, of length `numCoveringPoints` 5038552f7358SJed Brown 5039552f7358SJed Brown Level: intermediate 5040552f7358SJed Brown 5041a1cb98faSBarry Smith Note: 5042a1cb98faSBarry Smith Currently, this is restricted to a single level meet 5043552f7358SJed Brown 5044feaf08eaSBarry Smith Fortran Note: 50452c9a7b26SBarry Smith `coveringPoints` must be declared with 50462c9a7b26SBarry Smith .vb 50472c9a7b26SBarry Smith PetscInt, pointer :: coveringPoints(:) 50482c9a7b26SBarry Smith .ve 50492c9a7b26SBarry Smith 50501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 5051552f7358SJed Brown @*/ 50525d83a8b1SBarry Smith PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt *coveringPoints[]) 5053d71ae5a4SJacob Faibussowitsch { 5054552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5055552f7358SJed Brown PetscInt *meet[2]; 5056552f7358SJed Brown PetscInt meetSize, i = 0; 5057552f7358SJed Brown PetscInt dof, off, p, c, m; 50586302a7fbSVaclav Hapla PetscInt maxConeSize; 5059552f7358SJed Brown 5060552f7358SJed Brown PetscFunctionBegin; 5061552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50624f572ea9SToby Isaac PetscAssertPointer(points, 3); 50634f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 50644f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 50656302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 50666302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 50676302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 5068552f7358SJed Brown /* Copy in cone of first point */ 50699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 50709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 5071ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 5072552f7358SJed Brown /* Check each successive cone */ 5073552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 5074552f7358SJed Brown PetscInt newMeetSize = 0; 5075552f7358SJed Brown 50769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 50779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 5078552f7358SJed Brown for (c = 0; c < dof; ++c) { 5079552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 5080552f7358SJed Brown 5081552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5082552f7358SJed Brown if (point == meet[i][m]) { 5083552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5084552f7358SJed Brown break; 5085552f7358SJed Brown } 5086552f7358SJed Brown } 5087552f7358SJed Brown } 5088552f7358SJed Brown meetSize = newMeetSize; 5089552f7358SJed Brown i = 1 - i; 5090552f7358SJed Brown } 5091552f7358SJed Brown *numCoveringPoints = meetSize; 5092552f7358SJed Brown *coveringPoints = meet[i]; 50936302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 50943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5095552f7358SJed Brown } 5096552f7358SJed Brown 5097552f7358SJed Brown /*@C 50982c9a7b26SBarry Smith DMPlexRestoreMeet - Restore an array for the meet of the set of points obtained with `DMPlexGetMeet()` 5099552f7358SJed Brown 5100552f7358SJed Brown Not Collective 5101552f7358SJed Brown 5102552f7358SJed Brown Input Parameters: 5103a1cb98faSBarry Smith + dm - The `DMPLEX` object 5104552f7358SJed Brown . numPoints - The number of input points for the meet 5105552f7358SJed Brown - points - The input points 5106552f7358SJed Brown 5107552f7358SJed Brown Output Parameters: 5108552f7358SJed Brown + numCoveredPoints - The number of points in the meet 5109552f7358SJed Brown - coveredPoints - The points in the meet 5110552f7358SJed Brown 5111552f7358SJed Brown Level: intermediate 5112552f7358SJed Brown 51131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 5114552f7358SJed Brown @*/ 51155d83a8b1SBarry Smith PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5116d71ae5a4SJacob Faibussowitsch { 5117552f7358SJed Brown PetscFunctionBegin; 5118552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51194f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 51204f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 51214f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 51229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 5123d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 51243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5125552f7358SJed Brown } 5126552f7358SJed Brown 5127552f7358SJed Brown /*@C 5128552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 5129552f7358SJed Brown 5130552f7358SJed Brown Not Collective 5131552f7358SJed Brown 5132552f7358SJed Brown Input Parameters: 5133a1cb98faSBarry Smith + dm - The `DMPLEX` object 5134552f7358SJed Brown . numPoints - The number of input points for the meet 51352c9a7b26SBarry Smith - points - The input points, of length `numPoints` 5136552f7358SJed Brown 5137552f7358SJed Brown Output Parameters: 5138552f7358SJed Brown + numCoveredPoints - The number of points in the meet 51392c9a7b26SBarry Smith - coveredPoints - The points in the meet, of length `numCoveredPoints` 5140552f7358SJed Brown 5141552f7358SJed Brown Level: intermediate 5142552f7358SJed Brown 514360225df5SJacob Faibussowitsch Fortran Notes: 5144feaf08eaSBarry Smith `coveredPoints` must be declared with 51452c9a7b26SBarry Smith .vb 51462c9a7b26SBarry Smith PetscInt, pointer :: coveredPoints(:) 51472c9a7b26SBarry Smith .ve 51482c9a7b26SBarry Smith 51491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 5150552f7358SJed Brown @*/ 51515d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5152d71ae5a4SJacob Faibussowitsch { 5153552f7358SJed Brown PetscInt *offsets, **closures; 5154552f7358SJed Brown PetscInt *meet[2]; 5155552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 515624c766afSToby Isaac PetscInt p, h, c, m, mc; 5157552f7358SJed Brown 5158552f7358SJed Brown PetscFunctionBegin; 5159552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51604f572ea9SToby Isaac PetscAssertPointer(points, 3); 51614f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 51624f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 5163552f7358SJed Brown 51649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 51659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 51669566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 51676302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 516824c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 51699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 51709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 5171552f7358SJed Brown 5172552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 5173552f7358SJed Brown PetscInt closureSize; 5174552f7358SJed Brown 51759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 51760d644c17SKarl Rupp 5177552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 5178552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5179552f7358SJed Brown PetscInt pStart, pEnd, i; 5180552f7358SJed Brown 51819566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 5182552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 5183552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 5184552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 5185552f7358SJed Brown break; 5186552f7358SJed Brown } 5187552f7358SJed Brown } 5188552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 5189552f7358SJed Brown } 519063a3b9bcSJacob 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); 5191552f7358SJed Brown } 5192552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5193552f7358SJed Brown PetscInt dof; 5194552f7358SJed Brown 5195552f7358SJed Brown /* Copy in cone of first point */ 5196552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5197ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5198552f7358SJed Brown /* Check each successive cone */ 5199552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5200552f7358SJed Brown PetscInt newMeetSize = 0; 5201552f7358SJed Brown 5202552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5203552f7358SJed Brown for (c = 0; c < dof; ++c) { 5204552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5205552f7358SJed Brown 5206552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5207552f7358SJed Brown if (point == meet[i][m]) { 5208552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5209552f7358SJed Brown break; 5210552f7358SJed Brown } 5211552f7358SJed Brown } 5212552f7358SJed Brown } 5213552f7358SJed Brown meetSize = newMeetSize; 5214552f7358SJed Brown i = 1 - i; 5215552f7358SJed Brown } 5216552f7358SJed Brown if (meetSize) break; 5217552f7358SJed Brown } 5218552f7358SJed Brown *numCoveredPoints = meetSize; 5219552f7358SJed Brown *coveredPoints = meet[i]; 522048a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 52219566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 52229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 52236302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 52243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5225552f7358SJed Brown } 5226552f7358SJed Brown 5227cc4c1da9SBarry Smith /*@ 5228a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 52294e3744c5SMatthew G. Knepley 52304e3744c5SMatthew G. Knepley Not Collective 52314e3744c5SMatthew G. Knepley 52324e3744c5SMatthew G. Knepley Input Parameters: 5233a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5234a1cb98faSBarry Smith - dmB - A `DMPLEX` object 52354e3744c5SMatthew G. Knepley 52362fe279fdSBarry Smith Output Parameter: 5237a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 52384e3744c5SMatthew G. Knepley 52394e3744c5SMatthew G. Knepley Level: intermediate 52404e3744c5SMatthew G. Knepley 5241a1cb98faSBarry Smith Note: 52423c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 52434e3744c5SMatthew G. Knepley 52441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 52454e3744c5SMatthew G. Knepley @*/ 5246d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5247d71ae5a4SJacob Faibussowitsch { 52484e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 52494e3744c5SMatthew G. Knepley 52504e3744c5SMatthew G. Knepley PetscFunctionBegin; 52514e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 52524e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 52534f572ea9SToby Isaac PetscAssertPointer(equal, 3); 52544e3744c5SMatthew G. Knepley 52554e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 52569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 52579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 52583ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 52599566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 52609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 52613ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 52624e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 52634e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 52644e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 52654e3744c5SMatthew G. Knepley 52669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 52679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 52689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 52699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 52709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 52719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 52723ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 52734e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 52743ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52753ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52764e3744c5SMatthew G. Knepley } 52779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 52789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 52809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 52813ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 52824e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 52833ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 52844e3744c5SMatthew G. Knepley } 52854e3744c5SMatthew G. Knepley } 52864e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 52873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52884e3744c5SMatthew G. Knepley } 52894e3744c5SMatthew G. Knepley 5290cc4c1da9SBarry Smith /*@ 52917cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 52927cd05799SMatthew G. Knepley 52937cd05799SMatthew G. Knepley Not Collective 52947cd05799SMatthew G. Knepley 52957cd05799SMatthew G. Knepley Input Parameters: 5296a1cb98faSBarry Smith + dm - The `DMPLEX` 52977cd05799SMatthew G. Knepley . cellDim - The cell dimension 52987cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 52997cd05799SMatthew G. Knepley 53002fe279fdSBarry Smith Output Parameter: 53017cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 53027cd05799SMatthew G. Knepley 53037cd05799SMatthew G. Knepley Level: developer 53047cd05799SMatthew G. Knepley 5305a1cb98faSBarry Smith Note: 53067cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 53077cd05799SMatthew G. Knepley 53081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 53097cd05799SMatthew G. Knepley @*/ 5310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5311d71ae5a4SJacob Faibussowitsch { 531282f516ccSBarry Smith MPI_Comm comm; 5313552f7358SJed Brown 5314552f7358SJed Brown PetscFunctionBegin; 53159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 53164f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5317552f7358SJed Brown switch (cellDim) { 5318d71ae5a4SJacob Faibussowitsch case 0: 5319d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5320d71ae5a4SJacob Faibussowitsch break; 5321d71ae5a4SJacob Faibussowitsch case 1: 5322d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5323d71ae5a4SJacob Faibussowitsch break; 5324552f7358SJed Brown case 2: 5325552f7358SJed Brown switch (numCorners) { 532619436ca2SJed Brown case 3: /* triangle */ 532719436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5328552f7358SJed Brown break; 532919436ca2SJed Brown case 4: /* quadrilateral */ 533019436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5331552f7358SJed Brown break; 533219436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 533319436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5334552f7358SJed Brown break; 533519436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 533619436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5337552f7358SJed Brown break; 5338d71ae5a4SJacob Faibussowitsch default: 5339d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5340552f7358SJed Brown } 5341552f7358SJed Brown break; 5342552f7358SJed Brown case 3: 5343552f7358SJed Brown switch (numCorners) { 534419436ca2SJed Brown case 4: /* tetradehdron */ 534519436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5346552f7358SJed Brown break; 534719436ca2SJed Brown case 6: /* tet cohesive cells */ 534819436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5349552f7358SJed Brown break; 535019436ca2SJed Brown case 8: /* hexahedron */ 535119436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5352552f7358SJed Brown break; 535319436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 535419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5355552f7358SJed Brown break; 535619436ca2SJed Brown case 10: /* quadratic tetrahedron */ 535719436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5358552f7358SJed Brown break; 535919436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 536019436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5361552f7358SJed Brown break; 536219436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 536319436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5364552f7358SJed Brown break; 536519436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 536619436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5367552f7358SJed Brown break; 5368d71ae5a4SJacob Faibussowitsch default: 5369d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5370552f7358SJed Brown } 5371552f7358SJed Brown break; 5372d71ae5a4SJacob Faibussowitsch default: 5373d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5374552f7358SJed Brown } 53753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5376552f7358SJed Brown } 5377552f7358SJed Brown 5378552f7358SJed Brown /*@ 5379a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5380552f7358SJed Brown 5381552f7358SJed Brown Not Collective 5382552f7358SJed Brown 5383aa50250dSMatthew G. Knepley Input Parameter: 5384a1cb98faSBarry Smith . dm - The `DMPLEX` object 5385552f7358SJed Brown 5386aa50250dSMatthew G. Knepley Output Parameter: 5387a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5388552f7358SJed Brown 5389552f7358SJed Brown Level: developer 5390552f7358SJed Brown 53911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5392aa50250dSMatthew G. Knepley @*/ 5393d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5394d71ae5a4SJacob Faibussowitsch { 5395aa50250dSMatthew G. Knepley PetscFunctionBegin; 5396aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53974f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5398c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 53993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5400aa50250dSMatthew G. Knepley } 5401aa50250dSMatthew G. Knepley 5402aa50250dSMatthew G. Knepley /*@ 5403aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5404aa50250dSMatthew G. Knepley 5405aa50250dSMatthew G. Knepley Not Collective 5406aa50250dSMatthew G. Knepley 5407aa50250dSMatthew G. Knepley Input Parameter: 5408a1cb98faSBarry Smith . dm - The `DMPLEX` object 5409aa50250dSMatthew G. Knepley 5410aa50250dSMatthew G. Knepley Output Parameter: 5411aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5412aa50250dSMatthew G. Knepley 5413aa50250dSMatthew G. Knepley Level: developer 5414552f7358SJed Brown 5415b1bb481bSMatthew Knepley Notes: 5416a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5417a1cb98faSBarry Smith 5418a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5419a1cb98faSBarry Smith 5420dc287ab2SVaclav Hapla An empty mesh gives -1. 5421b1bb481bSMatthew Knepley 54221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5423552f7358SJed Brown @*/ 5424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5425d71ae5a4SJacob Faibussowitsch { 54269f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5427aa50250dSMatthew G. Knepley DMLabel label; 5428452349dbSMatthew G. Knepley PetscInt d = -1; 5429552f7358SJed Brown 5430552f7358SJed Brown PetscFunctionBegin; 5431552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54324f572ea9SToby Isaac PetscAssertPointer(depth, 2); 54339f4ada15SMatthew G. Knepley if (mesh->tr) { 54349f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 54359f4ada15SMatthew G. Knepley } else { 54369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 5437452349dbSMatthew G. Knepley // Allow missing depths 5438452349dbSMatthew G. Knepley if (label) PetscCall(DMLabelGetValueBounds(label, NULL, &d)); 5439452349dbSMatthew G. Knepley *depth = d; 54409f4ada15SMatthew G. Knepley } 54413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5442552f7358SJed Brown } 5443552f7358SJed Brown 5444552f7358SJed Brown /*@ 544520f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5446552f7358SJed Brown 5447552f7358SJed Brown Not Collective 5448552f7358SJed Brown 5449552f7358SJed Brown Input Parameters: 5450a1cb98faSBarry Smith + dm - The `DMPLEX` object 5451570fa34dSVaclav Hapla - depth - The requested depth 5452552f7358SJed Brown 5453552f7358SJed Brown Output Parameters: 545420f4b53cSBarry Smith + start - The first point at this `depth` 545520f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5456552f7358SJed Brown 5457552f7358SJed Brown Level: developer 5458552f7358SJed Brown 5459a1cb98faSBarry Smith Notes: 5460a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5461a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5462a1cb98faSBarry Smith higher dimension, e.g., "edges". 5463a1cb98faSBarry Smith 54642827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5465552f7358SJed Brown @*/ 5466ce78bad3SBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PeOp PetscInt *start, PeOp PetscInt *end) 5467d71ae5a4SJacob Faibussowitsch { 54689f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5469aa50250dSMatthew G. Knepley DMLabel label; 547063d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5471552f7358SJed Brown 5472552f7358SJed Brown PetscFunctionBegin; 5473552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54749371c9d4SSatish Balay if (start) { 54754f572ea9SToby Isaac PetscAssertPointer(start, 3); 54769371c9d4SSatish Balay *start = 0; 54779371c9d4SSatish Balay } 54789371c9d4SSatish Balay if (end) { 54794f572ea9SToby Isaac PetscAssertPointer(end, 4); 54809371c9d4SSatish Balay *end = 0; 54819371c9d4SSatish Balay } 54829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 54833ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5484570fa34dSVaclav Hapla if (depth < 0) { 548563d1a920SMatthew G. Knepley if (start) *start = pStart; 548663d1a920SMatthew G. Knepley if (end) *end = pEnd; 54873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5488552f7358SJed Brown } 54899f4ada15SMatthew G. Knepley if (mesh->tr) { 54909f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 54919f4ada15SMatthew G. Knepley } else { 54929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 549328b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5494570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 54959f4ada15SMatthew G. Knepley } 54963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5497552f7358SJed Brown } 5498552f7358SJed Brown 5499552f7358SJed Brown /*@ 550020f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5501552f7358SJed Brown 5502552f7358SJed Brown Not Collective 5503552f7358SJed Brown 5504552f7358SJed Brown Input Parameters: 5505a1cb98faSBarry Smith + dm - The `DMPLEX` object 5506570fa34dSVaclav Hapla - height - The requested height 5507552f7358SJed Brown 5508552f7358SJed Brown Output Parameters: 550920f4b53cSBarry Smith + start - The first point at this `height` 551020f4b53cSBarry Smith - end - One beyond the last point at this `height` 5511552f7358SJed Brown 5512552f7358SJed Brown Level: developer 5513552f7358SJed Brown 5514a1cb98faSBarry Smith Notes: 5515a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5516a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5517a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5518a1cb98faSBarry Smith 55192827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5520552f7358SJed Brown @*/ 5521ce78bad3SBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PeOp PetscInt *start, PeOp PetscInt *end) 5522d71ae5a4SJacob Faibussowitsch { 5523aa50250dSMatthew G. Knepley DMLabel label; 552463d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5525552f7358SJed Brown 5526552f7358SJed Brown PetscFunctionBegin; 5527552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55289371c9d4SSatish Balay if (start) { 55294f572ea9SToby Isaac PetscAssertPointer(start, 3); 55309371c9d4SSatish Balay *start = 0; 55319371c9d4SSatish Balay } 55329371c9d4SSatish Balay if (end) { 55334f572ea9SToby Isaac PetscAssertPointer(end, 4); 55349371c9d4SSatish Balay *end = 0; 55359371c9d4SSatish Balay } 55369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 55373ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5538570fa34dSVaclav Hapla if (height < 0) { 553963d1a920SMatthew G. Knepley if (start) *start = pStart; 554063d1a920SMatthew G. Knepley if (end) *end = pEnd; 55413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5542552f7358SJed Brown } 55439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 554459e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 554559e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 554659e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 554759e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 55483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5549552f7358SJed Brown } 5550552f7358SJed Brown 5551ba2698f1SMatthew G. Knepley /*@ 555220f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5553ba2698f1SMatthew G. Knepley 5554ba2698f1SMatthew G. Knepley Not Collective 5555ba2698f1SMatthew G. Knepley 5556d8d19677SJose E. Roman Input Parameters: 5557a1cb98faSBarry Smith + dm - The `DMPLEX` object 5558ba2698f1SMatthew G. Knepley - point - The point 5559ba2698f1SMatthew G. Knepley 5560ba2698f1SMatthew G. Knepley Output Parameter: 556120f4b53cSBarry Smith . depth - The depth of the `point` 5562ba2698f1SMatthew G. Knepley 5563ba2698f1SMatthew G. Knepley Level: intermediate 5564ba2698f1SMatthew G. Knepley 55651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5566ba2698f1SMatthew G. Knepley @*/ 5567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5568d71ae5a4SJacob Faibussowitsch { 5569ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5570ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55714f572ea9SToby Isaac PetscAssertPointer(depth, 3); 55729566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 55733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5574ba2698f1SMatthew G. Knepley } 5575ba2698f1SMatthew G. Knepley 5576ba2698f1SMatthew G. Knepley /*@ 557720f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 55780c0a32dcSVaclav Hapla 55790c0a32dcSVaclav Hapla Not Collective 55800c0a32dcSVaclav Hapla 5581d8d19677SJose E. Roman Input Parameters: 5582a1cb98faSBarry Smith + dm - The `DMPLEX` object 55830c0a32dcSVaclav Hapla - point - The point 55840c0a32dcSVaclav Hapla 55850c0a32dcSVaclav Hapla Output Parameter: 558620f4b53cSBarry Smith . height - The height of the `point` 55870c0a32dcSVaclav Hapla 55880c0a32dcSVaclav Hapla Level: intermediate 55890c0a32dcSVaclav Hapla 55901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 55910c0a32dcSVaclav Hapla @*/ 5592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5593d71ae5a4SJacob Faibussowitsch { 55940c0a32dcSVaclav Hapla PetscInt n, pDepth; 55950c0a32dcSVaclav Hapla 55960c0a32dcSVaclav Hapla PetscFunctionBegin; 55970c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55984f572ea9SToby Isaac PetscAssertPointer(height, 3); 55999566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 56009566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 56010c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 56023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56030c0a32dcSVaclav Hapla } 56040c0a32dcSVaclav Hapla 56050c0a32dcSVaclav Hapla /*@ 5606a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5607ba2698f1SMatthew G. Knepley 5608ba2698f1SMatthew G. Knepley Not Collective 5609ba2698f1SMatthew G. Knepley 5610ba2698f1SMatthew G. Knepley Input Parameter: 5611a1cb98faSBarry Smith . dm - The `DMPLEX` object 5612ba2698f1SMatthew G. Knepley 5613ba2698f1SMatthew G. Knepley Output Parameter: 5614a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5615412e9a14SMatthew G. Knepley 5616ba2698f1SMatthew G. Knepley Level: developer 5617ba2698f1SMatthew G. Knepley 5618a1cb98faSBarry Smith Note: 5619a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5620a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5621a1cb98faSBarry Smith 56221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5623ba2698f1SMatthew G. Knepley @*/ 5624d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5625d71ae5a4SJacob Faibussowitsch { 5626ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5627ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56284f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 56299566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5630ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 56313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5632ba2698f1SMatthew G. Knepley } 5633ba2698f1SMatthew G. Knepley 5634ba2698f1SMatthew G. Knepley /*@ 5635ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5636ba2698f1SMatthew G. Knepley 5637ba2698f1SMatthew G. Knepley Not Collective 5638ba2698f1SMatthew G. Knepley 5639d8d19677SJose E. Roman Input Parameters: 5640a1cb98faSBarry Smith + dm - The `DMPLEX` object 5641ba2698f1SMatthew G. Knepley - cell - The cell 5642ba2698f1SMatthew G. Knepley 5643ba2698f1SMatthew G. Knepley Output Parameter: 5644ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5645ba2698f1SMatthew G. Knepley 5646ba2698f1SMatthew G. Knepley Level: intermediate 5647ba2698f1SMatthew G. Knepley 56481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5649ba2698f1SMatthew G. Knepley @*/ 5650d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5651d71ae5a4SJacob Faibussowitsch { 56529f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5653ba2698f1SMatthew G. Knepley DMLabel label; 5654ba2698f1SMatthew G. Knepley PetscInt ct; 5655ba2698f1SMatthew G. Knepley 5656ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5657ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56584f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 56599f4ada15SMatthew G. Knepley if (mesh->tr) { 56609f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 56619f4ada15SMatthew G. Knepley } else { 566221027e53SStefano Zampini PetscInt pStart, pEnd; 566321027e53SStefano Zampini 566421027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 566521027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 566621027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 5667f4a55318SMatthew G. Knepley if (pEnd <= pStart) { 5668f4a55318SMatthew G. Knepley *celltype = DM_POLYTOPE_UNKNOWN; 5669f4a55318SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5670f4a55318SMatthew G. Knepley } 567121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 567221027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 567321027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 567421027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 56756497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 567621027e53SStefano Zampini } 567721027e53SStefano Zampini } 567821027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 567921027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 56809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 56819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 568263a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5683936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 568421027e53SStefano Zampini } 56859f4ada15SMatthew G. Knepley } 56863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5687ba2698f1SMatthew G. Knepley } 5688ba2698f1SMatthew G. Knepley 5689412e9a14SMatthew G. Knepley /*@ 5690412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5691412e9a14SMatthew G. Knepley 5692412e9a14SMatthew G. Knepley Not Collective 5693412e9a14SMatthew G. Knepley 5694412e9a14SMatthew G. Knepley Input Parameters: 5695a1cb98faSBarry Smith + dm - The `DMPLEX` object 5696412e9a14SMatthew G. Knepley . cell - The cell 5697412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5698412e9a14SMatthew G. Knepley 5699a1cb98faSBarry Smith Level: advanced 5700a1cb98faSBarry Smith 5701a1cb98faSBarry Smith Note: 5702a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5703412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5704412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5705db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5706412e9a14SMatthew G. Knepley 57071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5708412e9a14SMatthew G. Knepley @*/ 5709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5710d71ae5a4SJacob Faibussowitsch { 571121027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5712412e9a14SMatthew G. Knepley DMLabel label; 571321027e53SStefano Zampini PetscInt pStart, pEnd; 5714412e9a14SMatthew G. Knepley 5715412e9a14SMatthew G. Knepley PetscFunctionBegin; 5716412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 571721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 57189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 57199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 572021027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 57216497c311SBarry Smith mesh->cellTypes[cell - pStart].value_as_uint8 = (uint8_t)celltype; 57223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5723412e9a14SMatthew G. Knepley } 5724412e9a14SMatthew G. Knepley 5725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5726d71ae5a4SJacob Faibussowitsch { 5727c789d87fSToby Isaac PetscSection section; 57283e922f36SToby Isaac PetscInt maxHeight; 5729dd4c3f67SMatthew G. Knepley const char *prefix; 5730552f7358SJed Brown 5731552f7358SJed Brown PetscFunctionBegin; 57329566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5733dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5734dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5735dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 57369566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 57379566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 57389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 57399566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 57409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 57418f4c458bSMatthew G. Knepley 57429566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 57439566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5744dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5745dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 57463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5747552f7358SJed Brown } 5748552f7358SJed Brown 574999acd26cSksagiyam PetscErrorCode DMCreateCellCoordinateDM_Plex(DM dm, DM *cdm) 575099acd26cSksagiyam { 575199acd26cSksagiyam DM cgcdm; 575299acd26cSksagiyam PetscSection section; 575399acd26cSksagiyam const char *prefix; 575499acd26cSksagiyam 575599acd26cSksagiyam PetscFunctionBegin; 575699acd26cSksagiyam PetscCall(DMGetCoordinateDM(dm, &cgcdm)); 575799acd26cSksagiyam PetscCall(DMClone(cgcdm, cdm)); 575899acd26cSksagiyam PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 575999acd26cSksagiyam PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 576099acd26cSksagiyam PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cellcdm_")); 576199acd26cSksagiyam PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 576299acd26cSksagiyam PetscCall(DMSetLocalSection(*cdm, section)); 576399acd26cSksagiyam PetscCall(PetscSectionDestroy(§ion)); 576499acd26cSksagiyam PetscCall(DMSetNumFields(*cdm, 1)); 576599acd26cSksagiyam PetscCall(DMCreateDS(*cdm)); 576699acd26cSksagiyam (*cdm)->cloneOpts = PETSC_TRUE; 576799acd26cSksagiyam if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 576899acd26cSksagiyam PetscFunctionReturn(PETSC_SUCCESS); 576999acd26cSksagiyam } 577099acd26cSksagiyam 5771d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5772d71ae5a4SJacob Faibussowitsch { 57736858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 57746858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5775f19dbd58SToby Isaac 5776f19dbd58SToby Isaac PetscFunctionBegin; 5777f19dbd58SToby Isaac *field = NULL; 57789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 57799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 57806858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 57816858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5782f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 57836858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 57846858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5785f19dbd58SToby Isaac } 57863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5787f19dbd58SToby Isaac } 5788f19dbd58SToby Isaac 5789cc4c1da9SBarry Smith /*@ 57907cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 57917cd05799SMatthew G. Knepley 57927cd05799SMatthew G. Knepley Not Collective 57937cd05799SMatthew G. Knepley 57942fe279fdSBarry Smith Input Parameter: 5795a1cb98faSBarry Smith . dm - The `DMPLEX` object 57967cd05799SMatthew G. Knepley 57977cd05799SMatthew G. Knepley Output Parameter: 5798a1cb98faSBarry Smith . section - The `PetscSection` object 57997cd05799SMatthew G. Knepley 58007cd05799SMatthew G. Knepley Level: developer 58017cd05799SMatthew G. Knepley 58021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 58037cd05799SMatthew G. Knepley @*/ 5804d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5805d71ae5a4SJacob Faibussowitsch { 5806552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5807552f7358SJed Brown 5808552f7358SJed Brown PetscFunctionBegin; 5809552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5810552f7358SJed Brown if (section) *section = mesh->coneSection; 58113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5812552f7358SJed Brown } 5813552f7358SJed Brown 5814cc4c1da9SBarry Smith /*@ 58157cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 58167cd05799SMatthew G. Knepley 58177cd05799SMatthew G. Knepley Not Collective 58187cd05799SMatthew G. Knepley 58192fe279fdSBarry Smith Input Parameter: 5820a1cb98faSBarry Smith . dm - The `DMPLEX` object 58217cd05799SMatthew G. Knepley 58227cd05799SMatthew G. Knepley Output Parameter: 5823a1cb98faSBarry Smith . section - The `PetscSection` object 58247cd05799SMatthew G. Knepley 58257cd05799SMatthew G. Knepley Level: developer 58267cd05799SMatthew G. Knepley 58271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 58287cd05799SMatthew G. Knepley @*/ 5829d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5830d71ae5a4SJacob Faibussowitsch { 58318cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 58328cb4d582SMatthew G. Knepley 58338cb4d582SMatthew G. Knepley PetscFunctionBegin; 58348cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58358cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 58363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58378cb4d582SMatthew G. Knepley } 58388cb4d582SMatthew G. Knepley 58397cd05799SMatthew G. Knepley /*@C 58407cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 58417cd05799SMatthew G. Knepley 58427cd05799SMatthew G. Knepley Not Collective 58437cd05799SMatthew G. Knepley 58442fe279fdSBarry Smith Input Parameter: 5845a1cb98faSBarry Smith . dm - The `DMPLEX` object 58467cd05799SMatthew G. Knepley 58477cd05799SMatthew G. Knepley Output Parameter: 58487cd05799SMatthew G. Knepley . cones - The cone for each point 58497cd05799SMatthew G. Knepley 58507cd05799SMatthew G. Knepley Level: developer 58517cd05799SMatthew G. Knepley 58521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 58537cd05799SMatthew G. Knepley @*/ 5854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5855d71ae5a4SJacob Faibussowitsch { 5856552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5857552f7358SJed Brown 5858552f7358SJed Brown PetscFunctionBegin; 5859552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5860552f7358SJed Brown if (cones) *cones = mesh->cones; 58613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5862552f7358SJed Brown } 5863552f7358SJed Brown 58647cd05799SMatthew G. Knepley /*@C 58657cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 58667cd05799SMatthew G. Knepley 58677cd05799SMatthew G. Knepley Not Collective 58687cd05799SMatthew G. Knepley 58692fe279fdSBarry Smith Input Parameter: 5870a1cb98faSBarry Smith . dm - The `DMPLEX` object 58717cd05799SMatthew G. Knepley 58727cd05799SMatthew G. Knepley Output Parameter: 5873b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 58747cd05799SMatthew G. Knepley 58757cd05799SMatthew G. Knepley Level: developer 58767cd05799SMatthew G. Knepley 5877b5a892a1SMatthew G. Knepley Notes: 58782c9a7b26SBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points 58792c9a7b26SBarry Smith as returned by `DMPlexGetConeOrientation()`. 5880b5a892a1SMatthew G. Knepley 5881a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5882b5a892a1SMatthew G. Knepley 58831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 58847cd05799SMatthew G. Knepley @*/ 5885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5886d71ae5a4SJacob Faibussowitsch { 5887552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5888552f7358SJed Brown 5889552f7358SJed Brown PetscFunctionBegin; 5890552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5891552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 58923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5893552f7358SJed Brown } 5894552f7358SJed Brown 58954ee01570SBarry Smith /* FEM Support */ 5896552f7358SJed Brown 5897d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5898d2b2dc1eSMatthew G. Knepley { 5899d2b2dc1eSMatthew G. Knepley PetscInt depth; 5900d2b2dc1eSMatthew G. Knepley 5901d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5902d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5903d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5904d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5905d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5906d2b2dc1eSMatthew G. Knepley } 5907d2b2dc1eSMatthew G. Knepley 59085962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 59095962854dSMatthew G. Knepley { 59105962854dSMatthew G. Knepley PetscInt depth; 59115962854dSMatthew G. Knepley 59125962854dSMatthew G. Knepley PetscFunctionBegin; 59135962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 59145962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 59155962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 59165962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 59175962854dSMatthew G. Knepley } 59185962854dSMatthew G. Knepley 59199e8305c2SJed Brown /* 59209e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 59219e8305c2SJed Brown representing a line in the section. 59229e8305c2SJed Brown */ 59235f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5924d71ae5a4SJacob Faibussowitsch { 5925e327e467SRezgar Shakeri PetscObject obj; 5926e327e467SRezgar Shakeri PetscClassId id; 5927e327e467SRezgar Shakeri PetscFE fe = NULL; 5928e327e467SRezgar Shakeri 59299e8305c2SJed Brown PetscFunctionBeginHot; 59309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5931e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5932e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5933e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5934e327e467SRezgar Shakeri 5935e327e467SRezgar Shakeri if (!fe) { 5936e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 59379e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 59389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 59399e8305c2SJed Brown *k = *k / *Nc + 1; 5940e327e467SRezgar Shakeri } else { 5941e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 59425f82726aSMatthew G. Knepley PetscDualSpace dsp; 59435f82726aSMatthew G. Knepley 5944e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 59455f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 59465f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5947e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 59485f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 59495f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 59505f82726aSMatthew G. Knepley } 59515f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 59525f82726aSMatthew G. Knepley } 59535f82726aSMatthew G. Knepley 59545f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 59555f82726aSMatthew G. Knepley { 59565f82726aSMatthew G. Knepley PetscFunctionBeginHot; 59575f82726aSMatthew G. Knepley if (tensor) { 59585f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 59595f82726aSMatthew G. Knepley } else { 59605f82726aSMatthew G. Knepley switch (dim) { 59615f82726aSMatthew G. Knepley case 1: 59625f82726aSMatthew G. Knepley *dof = k + 1; 59635f82726aSMatthew G. Knepley break; 59645f82726aSMatthew G. Knepley case 2: 59655f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 59665f82726aSMatthew G. Knepley break; 59675f82726aSMatthew G. Knepley case 3: 59685f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 59695f82726aSMatthew G. Knepley break; 59705f82726aSMatthew G. Knepley default: 59715f82726aSMatthew G. Knepley *dof = 0; 59725f82726aSMatthew G. Knepley } 59739e8305c2SJed Brown } 59743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59759e8305c2SJed Brown } 59769e8305c2SJed Brown 5977a4355906SMatthew Knepley /*@ 5978bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5979bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 598020f4b53cSBarry Smith section provided (or the section of the `DM`). 5981a4355906SMatthew Knepley 5982a4355906SMatthew Knepley Input Parameters: 598320f4b53cSBarry Smith + dm - The `DM` 598420f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 598520f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5986a4355906SMatthew Knepley 5987bc1eb3faSJed Brown Example: 5988bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5989bc1eb3faSJed Brown .vb 5990bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5991bc1eb3faSJed Brown 5992bc1eb3faSJed Brown v4 -- e6 -- v3 5993bc1eb3faSJed Brown | | 5994bc1eb3faSJed Brown e7 c0 e8 5995bc1eb3faSJed Brown | | 5996bc1eb3faSJed Brown v1 -- e5 -- v2 5997bc1eb3faSJed Brown .ve 5998bc1eb3faSJed Brown 5999bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 6000bc1eb3faSJed Brown dofs in the order of points, e.g., 6001bc1eb3faSJed Brown .vb 6002bc1eb3faSJed Brown c0 -> [0,1,2,3] 6003bc1eb3faSJed Brown v1 -> [4] 6004bc1eb3faSJed Brown ... 6005bc1eb3faSJed Brown e5 -> [8, 9] 6006bc1eb3faSJed Brown .ve 6007bc1eb3faSJed Brown 6008bc1eb3faSJed Brown which corresponds to the dofs 6009bc1eb3faSJed Brown .vb 6010bc1eb3faSJed Brown 6 10 11 7 6011bc1eb3faSJed Brown 13 2 3 15 6012bc1eb3faSJed Brown 12 0 1 14 6013bc1eb3faSJed Brown 4 8 9 5 6014bc1eb3faSJed Brown .ve 6015bc1eb3faSJed Brown 6016bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 6017bc1eb3faSJed Brown .vb 6018bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 6019bc1eb3faSJed Brown .ve 6020bc1eb3faSJed Brown 6021bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 6022bc1eb3faSJed Brown .vb 6023bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 6024bc1eb3faSJed Brown .ve 6025bc1eb3faSJed Brown 6026a4355906SMatthew Knepley Level: developer 6027a4355906SMatthew Knepley 6028da9ac489SAlbert Cowie Notes: 6029a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 6030a1cb98faSBarry Smith degree of the basis. 6031a1cb98faSBarry Smith 6032da9ac489SAlbert Cowie This is required to run with libCEED. 6033da9ac489SAlbert Cowie 60341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 6035a4355906SMatthew Knepley @*/ 6036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 6037d71ae5a4SJacob Faibussowitsch { 60387391a63aSMatthew G. Knepley DMLabel label; 6039bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 60405f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 60413194fc30SMatthew G. Knepley 60423194fc30SMatthew G. Knepley PetscFunctionBegin; 60439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 60443ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 6045a433471fSStefano Zampini if (point < 0) { 6046a433471fSStefano Zampini PetscInt sStart, sEnd; 6047a433471fSStefano Zampini 60489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 6049a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 6050a433471fSStefano Zampini } 60519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 60529566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 60539566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 60549371c9d4SSatish Balay if (depth == 1) { 60559371c9d4SSatish Balay eStart = point; 60569371c9d4SSatish Balay } else if (depth == dim) { 60577391a63aSMatthew G. Knepley const PetscInt *cone; 60587391a63aSMatthew G. Knepley 60599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 6060d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 6061d4e6627bSStefano Zampini else if (dim == 3) { 6062d4e6627bSStefano Zampini const PetscInt *cone2; 60639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 6064d4e6627bSStefano Zampini eStart = cone2[0]; 606563a3b9bcSJacob 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); 606663a3b9bcSJacob 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); 6067e327e467SRezgar Shakeri 60689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 6069bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 6070bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 6071bb197d40SJed Brown PetscInt *perm; 6072bb197d40SJed Brown 60733194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 60745f82726aSMatthew G. Knepley PetscInt dof; 60755f82726aSMatthew G. Knepley 60765f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60775f82726aSMatthew 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); 60785f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 60795f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60805f82726aSMatthew G. Knepley size += dof * Nc; 60813194fc30SMatthew G. Knepley } 60829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 60833194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 6084bb197d40SJed Brown switch (d) { 6085babf31e0SJed Brown case 1: 60865f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60875f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 6088babf31e0SJed Brown /* 6089babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 6090babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 6091babf31e0SJed Brown */ 6092e327e467SRezgar Shakeri if (continuous) { 6093babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 60949371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 60959371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 6096babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 6097babf31e0SJed Brown foffset = offset; 6098e327e467SRezgar Shakeri } else { 60995f82726aSMatthew G. Knepley PetscInt dof; 61005f82726aSMatthew G. Knepley 61015f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 61025f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 61035f82726aSMatthew G. Knepley foffset = offset; 6104e327e467SRezgar Shakeri } 6105babf31e0SJed Brown break; 610689eabcffSMatthew G. Knepley case 2: 61073194fc30SMatthew 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} */ 61085f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 61095f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 61103194fc30SMatthew G. Knepley /* The SEM order is 61113194fc30SMatthew G. Knepley 61123194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 611389eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 61143194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 61153194fc30SMatthew G. Knepley */ 6116e327e467SRezgar Shakeri if (continuous) { 61173194fc30SMatthew G. Knepley const PetscInt of = 0; 61183194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 61193194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 61203194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 61213194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 61223194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 61233194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 61243194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 61253194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 61263194fc30SMatthew G. Knepley PetscInt o; 61273194fc30SMatthew G. Knepley 61283194fc30SMatthew G. Knepley /* bottom */ 61293194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 61309371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 61319371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61323194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 61333194fc30SMatthew G. Knepley /* middle */ 61343194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 61353194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 61369371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 61379371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61383194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 61393194fc30SMatthew G. Knepley } 61403194fc30SMatthew G. Knepley /* top */ 61413194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 61429371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 61439371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61443194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 61453194fc30SMatthew G. Knepley foffset = offset; 6146e327e467SRezgar Shakeri } else { 61475f82726aSMatthew G. Knepley PetscInt dof; 61485f82726aSMatthew G. Knepley 61495f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 61505f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 61515f82726aSMatthew G. Knepley foffset = offset; 61523194fc30SMatthew G. Knepley } 615389eabcffSMatthew G. Knepley break; 615489eabcffSMatthew G. Knepley case 3: 615589eabcffSMatthew G. Knepley /* The original hex closure is 615689eabcffSMatthew G. Knepley 615789eabcffSMatthew G. Knepley {c, 615889eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 615989eabcffSMatthew 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, 616089eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 616189eabcffSMatthew G. Knepley */ 61625f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 61635f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 616489eabcffSMatthew G. Knepley /* The SEM order is 616589eabcffSMatthew G. Knepley Bottom Slice 616689eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 616789eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 616889eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 616989eabcffSMatthew G. Knepley 617089eabcffSMatthew G. Knepley Middle Slice (j) 617189eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 617289eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 617389eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 617489eabcffSMatthew G. Knepley 617589eabcffSMatthew G. Knepley Top Slice 617689eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 617789eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 617889eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 617989eabcffSMatthew G. Knepley */ 6180e327e467SRezgar Shakeri if (continuous) { 618189eabcffSMatthew G. Knepley const PetscInt oc = 0; 618289eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 618389eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 618489eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 618589eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 618689eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 618789eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 618889eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 618989eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 619089eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 619189eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 619289eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 619389eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 619489eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 619589eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 619689eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 619789eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 619889eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 619989eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 620089eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 620189eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 620289eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 620389eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 620489eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 620589eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 620689eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 620789eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 620889eabcffSMatthew G. Knepley PetscInt o, n; 620989eabcffSMatthew G. Knepley 621089eabcffSMatthew G. Knepley /* Bottom Slice */ 621189eabcffSMatthew G. Knepley /* bottom */ 621289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 62139371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 62149371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 621589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 621689eabcffSMatthew G. Knepley /* middle */ 621789eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 621889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 62199371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 62209371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 62219371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 62229371c9d4SSatish Balay } 622389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 62243194fc30SMatthew G. Knepley } 622589eabcffSMatthew G. Knepley /* top */ 622689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 62279371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 62289371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 622989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 623089eabcffSMatthew G. Knepley 623189eabcffSMatthew G. Knepley /* Middle Slice */ 623289eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 623389eabcffSMatthew G. Knepley /* bottom */ 623489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 62359371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 62369371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 623789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 623889eabcffSMatthew G. Knepley /* middle */ 623989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 624089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 62419371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 62429371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 624389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 624489eabcffSMatthew G. Knepley } 624589eabcffSMatthew G. Knepley /* top */ 624689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 62479371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 62489371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 624989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 625089eabcffSMatthew G. Knepley } 625189eabcffSMatthew G. Knepley 625289eabcffSMatthew G. Knepley /* Top Slice */ 625389eabcffSMatthew G. Knepley /* bottom */ 625489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 62559371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 62569371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 625789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 625889eabcffSMatthew G. Knepley /* middle */ 625989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 626089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 62619371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 62629371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 626389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 626489eabcffSMatthew G. Knepley } 626589eabcffSMatthew G. Knepley /* top */ 626689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 62679371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 62689371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 626989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 627089eabcffSMatthew G. Knepley 627189eabcffSMatthew G. Knepley foffset = offset; 6272e327e467SRezgar Shakeri } else { 62735f82726aSMatthew G. Knepley PetscInt dof; 62745f82726aSMatthew G. Knepley 62755f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 62765f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 62775f82726aSMatthew G. Knepley foffset = offset; 627889eabcffSMatthew G. Knepley } 627989eabcffSMatthew G. Knepley break; 6280d71ae5a4SJacob Faibussowitsch default: 6281d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 628289eabcffSMatthew G. Knepley } 628389eabcffSMatthew G. Knepley } 628463a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 62853194fc30SMatthew G. Knepley /* Check permutation */ 62863194fc30SMatthew G. Knepley { 62873194fc30SMatthew G. Knepley PetscInt *check; 62883194fc30SMatthew G. Knepley 62899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 62901dca8a05SBarry Smith for (i = 0; i < size; ++i) { 62911dca8a05SBarry Smith check[i] = -1; 62921dca8a05SBarry 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]); 62931dca8a05SBarry Smith } 62943194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 62951dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 62969566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 62973194fc30SMatthew G. Knepley } 62989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6299a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6300a05c9aa3SJed Brown PetscInt *loc_perm; 63019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6302a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6303a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6304a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6305a05c9aa3SJed Brown } 63069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6307a05c9aa3SJed Brown } 6308bb197d40SJed Brown } 63093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63103194fc30SMatthew G. Knepley } 63113194fc30SMatthew G. Knepley 6312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6313d71ae5a4SJacob Faibussowitsch { 6314e071409bSToby Isaac PetscDS prob; 6315e071409bSToby Isaac PetscInt depth, Nf, h; 6316e071409bSToby Isaac DMLabel label; 6317e071409bSToby Isaac 6318e071409bSToby Isaac PetscFunctionBeginHot; 63199566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6320e071409bSToby Isaac Nf = prob->Nf; 6321e071409bSToby Isaac label = dm->depthLabel; 6322e071409bSToby Isaac *dspace = NULL; 6323e071409bSToby Isaac if (field < Nf) { 6324e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6325e071409bSToby Isaac 6326e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6327e071409bSToby Isaac PetscDualSpace dsp; 6328e071409bSToby Isaac 63299566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 63309566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 63319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6332e071409bSToby Isaac h = depth - 1 - h; 6333e071409bSToby Isaac if (h) { 63349566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6335e071409bSToby Isaac } else { 6336e071409bSToby Isaac *dspace = dsp; 6337e071409bSToby Isaac } 6338e071409bSToby Isaac } 6339e071409bSToby Isaac } 63403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6341e071409bSToby Isaac } 6342e071409bSToby Isaac 6343d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6344d71ae5a4SJacob Faibussowitsch { 634528351e22SJed Brown PetscScalar *array; 634628351e22SJed Brown const PetscScalar *vArray; 6347d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 63481a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6349552f7358SJed Brown 63501b406b76SMatthew G. Knepley PetscFunctionBeginHot; 63519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 63529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 63539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 63549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 63553f7cbbe7SMatthew G. Knepley if (!values || !*values) { 63569df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 63579df71ca4SMatthew G. Knepley PetscInt dof; 6358d9917b9dSMatthew G. Knepley 63599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 63609df71ca4SMatthew G. Knepley size += dof; 63619df71ca4SMatthew G. Knepley } 63629df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 63639df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 63642a3aaacfSMatthew G. Knepley PetscInt dof; 63655a1bb5cfSMatthew G. Knepley 63665a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 63679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 63685a1bb5cfSMatthew G. Knepley size += dof; 63695a1bb5cfSMatthew G. Knepley } 63703f7cbbe7SMatthew G. Knepley if (!values) { 63713f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 63723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63733f7cbbe7SMatthew G. Knepley } 63749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6375982e9ed1SMatthew G. Knepley } else { 6376982e9ed1SMatthew G. Knepley array = *values; 6377982e9ed1SMatthew G. Knepley } 63789df71ca4SMatthew G. Knepley size = 0; 637928351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 63809df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 63819df71ca4SMatthew G. Knepley PetscInt dof, off, d; 638228351e22SJed Brown const PetscScalar *varr; 6383d9917b9dSMatthew G. Knepley 63849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 63859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 63868e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6387ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 63889df71ca4SMatthew G. Knepley size += dof; 63899df71ca4SMatthew G. Knepley } 63909df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 63919df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 63929df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 63935a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 639428351e22SJed Brown const PetscScalar *varr; 63955a1bb5cfSMatthew G. Knepley 639652ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 63979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 63989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 63998e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 64005a1bb5cfSMatthew G. Knepley if (o >= 0) { 6401ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 64025a1bb5cfSMatthew G. Knepley } else { 6403ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 64045a1bb5cfSMatthew G. Knepley } 64059df71ca4SMatthew G. Knepley size += dof; 64065a1bb5cfSMatthew G. Knepley } 640728351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 64089df71ca4SMatthew G. Knepley if (!*values) { 64095a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 64105a1bb5cfSMatthew G. Knepley *values = array; 64119df71ca4SMatthew G. Knepley } else { 641263a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 64138c312ff3SMatthew G. Knepley *csize = size; 64149df71ca4SMatthew G. Knepley } 64153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64165a1bb5cfSMatthew G. Knepley } 6417d9917b9dSMatthew G. Knepley 641827f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6419d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6420d71ae5a4SJacob Faibussowitsch { 642127f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 642227f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 642327f02ce8SMatthew G. Knepley 64249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 642527f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 642627f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 642727f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 642827f02ce8SMatthew G. Knepley points[q * 2] = r; 642927f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 643027f02ce8SMatthew G. Knepley ++q; 643127f02ce8SMatthew G. Knepley } 643227f02ce8SMatthew G. Knepley } 643327f02ce8SMatthew G. Knepley *numPoints = q; 64343ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 643527f02ce8SMatthew G. Knepley } 643627f02ce8SMatthew G. Knepley 643797529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 643807218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6439d71ae5a4SJacob Faibussowitsch { 644027f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6441923c78e0SToby Isaac PetscInt np, *pts = NULL; 6442923c78e0SToby Isaac 6443923c78e0SToby Isaac PetscFunctionBeginHot; 64449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 644507218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6446923c78e0SToby Isaac PetscInt dof, off; 6447923c78e0SToby Isaac 64489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 64499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 64509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6451923c78e0SToby Isaac np = dof / 2; 64528e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 645327f02ce8SMatthew G. Knepley } else { 645407218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 64559566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6456923c78e0SToby Isaac } 6457923c78e0SToby Isaac *numPoints = np; 6458923c78e0SToby Isaac *points = pts; 6459923c78e0SToby Isaac *clp = cla; 64603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6461923c78e0SToby Isaac } 6462923c78e0SToby Isaac 6463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6464d71ae5a4SJacob Faibussowitsch { 6465923c78e0SToby Isaac PetscFunctionBeginHot; 6466923c78e0SToby Isaac if (!*clPoints) { 64679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6468923c78e0SToby Isaac } else { 64699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6470923c78e0SToby Isaac } 6471923c78e0SToby Isaac *numPoints = 0; 6472923c78e0SToby Isaac *points = NULL; 6473923c78e0SToby Isaac *clSec = NULL; 6474923c78e0SToby Isaac *clPoints = NULL; 6475923c78e0SToby Isaac *clp = NULL; 64763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6477923c78e0SToby Isaac } 6478923c78e0SToby Isaac 6479d71ae5a4SJacob 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[]) 6480d71ae5a4SJacob Faibussowitsch { 64811a271a75SMatthew G. Knepley PetscInt offset = 0, p; 648297e99dd9SToby Isaac const PetscInt **perms = NULL; 648397e99dd9SToby Isaac const PetscScalar **flips = NULL; 64841a271a75SMatthew G. Knepley 64851a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6486fe02ba77SJed Brown *size = 0; 64879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 648897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 648997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 649097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64921a271a75SMatthew G. Knepley PetscInt dof, off, d; 64931a271a75SMatthew G. Knepley const PetscScalar *varr; 64941a271a75SMatthew G. Knepley 64959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 64969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 64978e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 649897e99dd9SToby Isaac if (clperm) { 649997e99dd9SToby Isaac if (perm) { 650097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 65011a271a75SMatthew G. Knepley } else { 650297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 650397e99dd9SToby Isaac } 650497e99dd9SToby Isaac if (flip) { 650597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 650697e99dd9SToby Isaac } 650797e99dd9SToby Isaac } else { 650897e99dd9SToby Isaac if (perm) { 650997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 651097e99dd9SToby Isaac } else { 651197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 651297e99dd9SToby Isaac } 651397e99dd9SToby Isaac if (flip) { 651497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 65151a271a75SMatthew G. Knepley } 65161a271a75SMatthew G. Knepley } 651797e99dd9SToby Isaac offset += dof; 651897e99dd9SToby Isaac } 65199566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 65201a271a75SMatthew G. Knepley *size = offset; 65213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65221a271a75SMatthew G. Knepley } 65231a271a75SMatthew G. Knepley 6524d71ae5a4SJacob 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[]) 6525d71ae5a4SJacob Faibussowitsch { 65261a271a75SMatthew G. Knepley PetscInt offset = 0, f; 65271a271a75SMatthew G. Knepley 65281a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6529fe02ba77SJed Brown *size = 0; 65301a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 653197e99dd9SToby Isaac PetscInt p; 653297e99dd9SToby Isaac const PetscInt **perms = NULL; 653397e99dd9SToby Isaac const PetscScalar **flips = NULL; 65341a271a75SMatthew G. Knepley 65359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 653697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 653797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 653897e99dd9SToby Isaac PetscInt fdof, foff, b; 65391a271a75SMatthew G. Knepley const PetscScalar *varr; 654097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 654197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65421a271a75SMatthew G. Knepley 65439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 65449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 65451a271a75SMatthew G. Knepley varr = &vArray[foff]; 654697e99dd9SToby Isaac if (clperm) { 65479371c9d4SSatish Balay if (perm) { 6548ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 65491a271a75SMatthew G. Knepley } else { 6550ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 65519371c9d4SSatish Balay } 65529371c9d4SSatish Balay if (flip) { 6553ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 65549371c9d4SSatish Balay } 65559371c9d4SSatish Balay } else { 65569371c9d4SSatish Balay if (perm) { 6557ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 65589371c9d4SSatish Balay } else { 6559ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 65609371c9d4SSatish Balay } 65619371c9d4SSatish Balay if (flip) { 6562ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 65639371c9d4SSatish Balay } 65641a271a75SMatthew G. Knepley } 656597e99dd9SToby Isaac offset += fdof; 65661a271a75SMatthew G. Knepley } 65679566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 65681a271a75SMatthew G. Knepley } 65691a271a75SMatthew G. Knepley *size = offset; 65703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65711a271a75SMatthew G. Knepley } 65721a271a75SMatthew G. Knepley 657348162695SZach Atkins /*@C 657448162695SZach Atkins DMPlexVecGetOrientedClosure - Get an array of the values on the closure of 'point' with a given orientation, optionally applying the closure permutation. 657548162695SZach Atkins 657648162695SZach Atkins Not collective 657748162695SZach Atkins 657848162695SZach Atkins Input Parameters: 657948162695SZach Atkins + dm - The `DM` 658048162695SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 658148162695SZach Atkins . useClPerm - Flag for whether the provided closure permutation should be applied to the values 658248162695SZach Atkins . v - The local vector 658348162695SZach Atkins . point - The point in the `DM` 658448162695SZach Atkins - ornt - The orientation of the cell, an integer giving the prescription for cone traversal. Typically, this will be 0. 658548162695SZach Atkins 658648162695SZach Atkins Input/Output Parameters: 658748162695SZach Atkins + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 658848162695SZach Atkins - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 658948162695SZach Atkins if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 659048162695SZach Atkins 659148162695SZach Atkins Level: advanced 659248162695SZach Atkins 659348162695SZach Atkins Notes: 659448162695SZach Atkins `DMPlexVecGetOrientedClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 659548162695SZach Atkins calling function. This is because `DMPlexVecGetOrientedClosure()` is typically called in the inner loop of a `Vec` or `Mat` 659648162695SZach Atkins assembly function, and a user may already have allocated storage for this operation. 659748162695SZach Atkins 659848162695SZach Atkins Fortran Notes: 659948162695SZach Atkins The `csize` argument is present in the Fortran binding. Since the Fortran `values` array contains its length information this argument may not be needed. 660048162695SZach Atkins In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 660148162695SZach Atkins 660248162695SZach Atkins `values` must be declared with 660348162695SZach Atkins .vb 660448162695SZach Atkins PetscScalar,dimension(:),pointer :: values 660548162695SZach Atkins .ve 660648162695SZach Atkins and it will be allocated internally by PETSc to hold the values returned 660748162695SZach Atkins 660848162695SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexGetCellCoordinates()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()` 660948162695SZach Atkins @*/ 661048162695SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 661107218a29SMatthew G. Knepley { 661207218a29SMatthew G. Knepley PetscSection clSection; 661307218a29SMatthew G. Knepley IS clPoints; 661407218a29SMatthew G. Knepley PetscInt *points = NULL; 6615e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 661607218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 661707218a29SMatthew G. Knepley 661807218a29SMatthew G. Knepley PetscFunctionBeginHot; 661907218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 662007218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 662107218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6622e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 662307218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 662407218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 662507218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 662607218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 662707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 662807218a29SMatthew G. Knepley } 662907218a29SMatthew G. Knepley /* Get points */ 663007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 663107218a29SMatthew G. Knepley /* Get sizes */ 663207218a29SMatthew G. Knepley asize = 0; 663307218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 663407218a29SMatthew G. Knepley PetscInt dof; 663507218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 663607218a29SMatthew G. Knepley asize += dof; 663707218a29SMatthew G. Knepley } 663807218a29SMatthew G. Knepley if (values) { 663907218a29SMatthew G. Knepley const PetscScalar *vArray; 664007218a29SMatthew G. Knepley PetscInt size; 664107218a29SMatthew G. Knepley 664207218a29SMatthew G. Knepley if (*values) { 664307218a29SMatthew 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); 664407218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6645e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 664607218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 664707218a29SMatthew G. Knepley /* Get values */ 664807218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 664907218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 665007218a29SMatthew 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); 665107218a29SMatthew G. Knepley /* Cleanup array */ 665207218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 665307218a29SMatthew G. Knepley } 665407218a29SMatthew G. Knepley if (csize) *csize = asize; 665507218a29SMatthew G. Knepley /* Cleanup points */ 665607218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 665707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 665807218a29SMatthew G. Knepley } 665907218a29SMatthew G. Knepley 6660552f7358SJed Brown /*@C 6661552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6662552f7358SJed Brown 6663552f7358SJed Brown Not collective 6664552f7358SJed Brown 6665552f7358SJed Brown Input Parameters: 6666a1cb98faSBarry Smith + dm - The `DM` 666720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6668552f7358SJed Brown . v - The local vector 6669a1cb98faSBarry Smith - point - The point in the `DM` 6670552f7358SJed Brown 66716b867d5aSJose E. Roman Input/Output Parameters: 667220f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 66732c9a7b26SBarry Smith - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 66742c9a7b26SBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 667522c1ee49SMatthew G. Knepley 6676552f7358SJed Brown Level: intermediate 6677552f7358SJed Brown 6678a1cb98faSBarry Smith Notes: 667944a422c4SJames Wright This is used for getting the all values in a `Vec` in the closure of a mesh point. 668044a422c4SJames Wright To get only the values in the closure of a mesh point at a specific depth (for example, at mesh vertices), use `DMPlexVecGetClosureAtDepth()`. 668144a422c4SJames Wright 668220f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6683a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6684a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6685a1cb98faSBarry Smith 6686a1cb98faSBarry Smith A typical use could be 6687a1cb98faSBarry Smith .vb 6688a1cb98faSBarry Smith values = NULL; 6689a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6690a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6691a1cb98faSBarry Smith <Compute on closure> 6692a1cb98faSBarry Smith } 6693a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6694a1cb98faSBarry Smith .ve 6695a1cb98faSBarry Smith or 6696a1cb98faSBarry Smith .vb 6697a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6698a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6699a1cb98faSBarry Smith clSize = clMaxSize; 6700a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6701a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6702a1cb98faSBarry Smith <Compute on closure> 6703a1cb98faSBarry Smith } 6704a1cb98faSBarry Smith } 6705a1cb98faSBarry Smith PetscFree(values); 6706a1cb98faSBarry Smith .ve 6707a1cb98faSBarry Smith 670860225df5SJacob Faibussowitsch Fortran Notes: 6709ce78bad3SBarry Smith The `csize` argument is present in the Fortran binding. Since the Fortran `values` array contains its length information this argument may not be needed. 6710ce78bad3SBarry Smith In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 6711a1cb98faSBarry Smith 6712f13dfd9eSBarry Smith `values` must be declared with 6713f13dfd9eSBarry Smith .vb 6714f13dfd9eSBarry Smith PetscScalar,dimension(:),pointer :: values 6715f13dfd9eSBarry Smith .ve 6716f13dfd9eSBarry Smith and it will be allocated internally by PETSc to hold the values returned 6717f13dfd9eSBarry Smith 671844a422c4SJames Wright .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosureAtDepth()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6719552f7358SJed Brown @*/ 6720d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6721d71ae5a4SJacob Faibussowitsch { 6722d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 672348162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 67243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6725552f7358SJed Brown } 6726552f7358SJed Brown 672744a422c4SJames Wright /*@C 672844a422c4SJames Wright DMPlexVecGetClosureAtDepth - Get an array of the values on the closure of 'point' that are at a specific depth 672944a422c4SJames Wright 673044a422c4SJames Wright Not collective 673144a422c4SJames Wright 673244a422c4SJames Wright Input Parameters: 673344a422c4SJames Wright + dm - The `DM` 673444a422c4SJames Wright . section - The section describing the layout in `v`, or `NULL` to use the default section 673544a422c4SJames Wright . v - The local vector 673644a422c4SJames Wright . depth - The depth of mesh points that should be returned 673744a422c4SJames Wright - point - The point in the `DM` 673844a422c4SJames Wright 673944a422c4SJames Wright Input/Output Parameters: 674044a422c4SJames Wright + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 674144a422c4SJames Wright - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 674244a422c4SJames Wright if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 674344a422c4SJames Wright 674444a422c4SJames Wright Level: intermediate 674544a422c4SJames Wright 674644a422c4SJames Wright Notes: 674744a422c4SJames Wright This is used for getting the values in a `Vec` associated with specific mesh points. 674844a422c4SJames Wright For example, to get only the values at mesh vertices, pass `depth=0`. To get all the values in the closure of a mesh point, use `DMPlexVecGetClosure()`. 674944a422c4SJames Wright 675044a422c4SJames Wright `DMPlexVecGetClosureAtDepth()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 675144a422c4SJames Wright calling function. This is because `DMPlexVecGetClosureAtDepth()` is typically called in the inner loop of a `Vec` or `Mat` 675244a422c4SJames Wright assembly function, and a user may already have allocated storage for this operation. 675344a422c4SJames Wright 675444a422c4SJames Wright A typical use could be 675544a422c4SJames Wright .vb 675644a422c4SJames Wright values = NULL; 675744a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(dm, NULL, v, p, depth, &clSize, &values)); 675844a422c4SJames Wright for (cl = 0; cl < clSize; ++cl) { 675944a422c4SJames Wright <Compute on closure> 676044a422c4SJames Wright } 676144a422c4SJames Wright PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 676244a422c4SJames Wright .ve 676344a422c4SJames Wright or 676444a422c4SJames Wright .vb 676544a422c4SJames Wright PetscMalloc1(clMaxSize, &values); 676644a422c4SJames Wright for (p = pStart; p < pEnd; ++p) { 676744a422c4SJames Wright clSize = clMaxSize; 676844a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(dm, NULL, v, p, depth, &clSize, &values)); 676944a422c4SJames Wright for (cl = 0; cl < clSize; ++cl) { 677044a422c4SJames Wright <Compute on closure> 677144a422c4SJames Wright } 677244a422c4SJames Wright } 677344a422c4SJames Wright PetscFree(values); 677444a422c4SJames Wright .ve 677544a422c4SJames Wright 677644a422c4SJames Wright Fortran Notes: 677744a422c4SJames Wright The `csize` argument is present in the Fortran binding. Since the Fortran `values` array contains its length information this argument may not be needed. 677844a422c4SJames Wright In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 677944a422c4SJames Wright 678044a422c4SJames Wright `values` must be declared with 678144a422c4SJames Wright .vb 678244a422c4SJames Wright PetscScalar,dimension(:),pointer :: values 678344a422c4SJames Wright .ve 678444a422c4SJames Wright and it will be allocated internally by PETSc to hold the values returned 678544a422c4SJames Wright 678644a422c4SJames Wright .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 678744a422c4SJames Wright @*/ 678844a422c4SJames Wright PetscErrorCode DMPlexVecGetClosureAtDepth(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6789d71ae5a4SJacob Faibussowitsch { 6790e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6791e5c487bfSMatthew G. Knepley PetscSection clSection; 6792e5c487bfSMatthew G. Knepley IS clPoints; 6793e5c487bfSMatthew G. Knepley PetscScalar *array; 6794e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6795e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6796c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6797c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6798e5c487bfSMatthew G. Knepley 6799e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6800e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 68019566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6802e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6803e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 68049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 68059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 68069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6807e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 68089566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 68093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6810e5c487bfSMatthew G. Knepley } 6811e5c487bfSMatthew G. Knepley /* Get points */ 681207218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6813c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6814c459fbc1SJed Brown PetscInt dof; 68159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6816c459fbc1SJed Brown clsize += dof; 6817c459fbc1SJed Brown } 68189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6819e5c487bfSMatthew G. Knepley /* Filter points */ 6820e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6821e5c487bfSMatthew G. Knepley PetscInt dep; 6822e5c487bfSMatthew G. Knepley 68239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6824e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6825e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6826e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6827e5c487bfSMatthew G. Knepley ++Np; 6828e5c487bfSMatthew G. Knepley } 6829e5c487bfSMatthew G. Knepley /* Get array */ 6830e5c487bfSMatthew G. Knepley if (!values || !*values) { 6831e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6832e5c487bfSMatthew G. Knepley 6833e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 68349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6835e5c487bfSMatthew G. Knepley asize += dof; 6836e5c487bfSMatthew G. Knepley } 6837e5c487bfSMatthew G. Knepley if (!values) { 68389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6839e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 68403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6841e5c487bfSMatthew G. Knepley } 68429566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6843e5c487bfSMatthew G. Knepley } else { 6844e5c487bfSMatthew G. Knepley array = *values; 6845e5c487bfSMatthew G. Knepley } 68469566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6847e5c487bfSMatthew G. Knepley /* Get values */ 68489566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 68499566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6850e5c487bfSMatthew G. Knepley /* Cleanup points */ 68519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6852e5c487bfSMatthew G. Knepley /* Cleanup array */ 68539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6854e5c487bfSMatthew G. Knepley if (!*values) { 6855e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6856e5c487bfSMatthew G. Knepley *values = array; 6857e5c487bfSMatthew G. Knepley } else { 685863a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6859e5c487bfSMatthew G. Knepley *csize = size; 6860e5c487bfSMatthew G. Knepley } 68613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6862e5c487bfSMatthew G. Knepley } 6863e5c487bfSMatthew G. Knepley 6864552f7358SJed Brown /*@C 6865f13dfd9eSBarry Smith DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' obtained with `DMPlexVecGetClosure()` 6866552f7358SJed Brown 6867552f7358SJed Brown Not collective 6868552f7358SJed Brown 6869552f7358SJed Brown Input Parameters: 6870a1cb98faSBarry Smith + dm - The `DM` 687120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6872552f7358SJed Brown . v - The local vector 6873a1cb98faSBarry Smith . point - The point in the `DM` 687420f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6875f13dfd9eSBarry Smith - values - The array of values 6876552f7358SJed Brown 6877552f7358SJed Brown Level: intermediate 6878552f7358SJed Brown 6879a1cb98faSBarry Smith Note: 688020f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6881a1cb98faSBarry Smith 6882f13dfd9eSBarry Smith Fortran Note: 6883ce78bad3SBarry Smith The `csize` argument is present in the Fortran binding. Since the Fortran `values` array contains its length information this argument may not be needed. 6884ce78bad3SBarry Smith In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 6885a1cb98faSBarry Smith 68861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6887552f7358SJed Brown @*/ 6888d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6889d71ae5a4SJacob Faibussowitsch { 6890552f7358SJed Brown PetscInt size = 0; 6891552f7358SJed Brown 6892552f7358SJed Brown PetscFunctionBegin; 6893552f7358SJed Brown /* Should work without recalculating size */ 68949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6895c9fdaa05SMatthew G. Knepley *values = NULL; 68963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6897552f7358SJed Brown } 6898552f7358SJed Brown 6899d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6900d71ae5a4SJacob Faibussowitsch { 69019371c9d4SSatish Balay *x += y; 69029371c9d4SSatish Balay } 6903d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6904d71ae5a4SJacob Faibussowitsch { 69059371c9d4SSatish Balay *x = y; 69069371c9d4SSatish Balay } 6907552f7358SJed Brown 6908d71ae5a4SJacob 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[]) 6909d71ae5a4SJacob Faibussowitsch { 6910552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6911552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6912552f7358SJed Brown PetscScalar *a; 6913552f7358SJed Brown PetscInt off, cind = 0, k; 6914552f7358SJed Brown 6915552f7358SJed Brown PetscFunctionBegin; 69169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 69179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6918552f7358SJed Brown a = &array[off]; 6919552f7358SJed Brown if (!cdof || setBC) { 692097e99dd9SToby Isaac if (clperm) { 69219371c9d4SSatish Balay if (perm) { 6922ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6923552f7358SJed Brown } else { 6924ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 69259371c9d4SSatish Balay } 69269371c9d4SSatish Balay } else { 69279371c9d4SSatish Balay if (perm) { 6928ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 69299371c9d4SSatish Balay } else { 6930ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 69319371c9d4SSatish Balay } 6932552f7358SJed Brown } 6933552f7358SJed Brown } else { 69349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 693597e99dd9SToby Isaac if (clperm) { 69369371c9d4SSatish Balay if (perm) { 69379371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 69389371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69399371c9d4SSatish Balay ++cind; 69409371c9d4SSatish Balay continue; 69419371c9d4SSatish Balay } 694297e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6943552f7358SJed Brown } 6944552f7358SJed Brown } else { 6945552f7358SJed Brown for (k = 0; k < dof; ++k) { 69469371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69479371c9d4SSatish Balay ++cind; 69489371c9d4SSatish Balay continue; 69499371c9d4SSatish Balay } 695097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 695197e99dd9SToby Isaac } 695297e99dd9SToby Isaac } 695397e99dd9SToby Isaac } else { 695497e99dd9SToby Isaac if (perm) { 695597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 69569371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69579371c9d4SSatish Balay ++cind; 69589371c9d4SSatish Balay continue; 69599371c9d4SSatish Balay } 696097e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 696197e99dd9SToby Isaac } 696297e99dd9SToby Isaac } else { 696397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 69649371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69659371c9d4SSatish Balay ++cind; 69669371c9d4SSatish Balay continue; 69679371c9d4SSatish Balay } 696897e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 696997e99dd9SToby Isaac } 6970552f7358SJed Brown } 6971552f7358SJed Brown } 6972552f7358SJed Brown } 69733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6974552f7358SJed Brown } 6975552f7358SJed Brown 6976d71ae5a4SJacob 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[]) 6977d71ae5a4SJacob Faibussowitsch { 6978a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6979a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6980a5e93ea8SMatthew G. Knepley PetscScalar *a; 6981a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6982a5e93ea8SMatthew G. Knepley 6983a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 69849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 69859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6986a5e93ea8SMatthew G. Knepley a = &array[off]; 6987a5e93ea8SMatthew G. Knepley if (cdof) { 69889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 698997e99dd9SToby Isaac if (clperm) { 699097e99dd9SToby Isaac if (perm) { 6991a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6992a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 699397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 699497e99dd9SToby Isaac cind++; 6995a5e93ea8SMatthew G. Knepley } 6996a5e93ea8SMatthew G. Knepley } 6997a5e93ea8SMatthew G. Knepley } else { 6998a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6999a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 700097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 700197e99dd9SToby Isaac cind++; 700297e99dd9SToby Isaac } 700397e99dd9SToby Isaac } 700497e99dd9SToby Isaac } 700597e99dd9SToby Isaac } else { 700697e99dd9SToby Isaac if (perm) { 700797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 700897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 700997e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 701097e99dd9SToby Isaac cind++; 701197e99dd9SToby Isaac } 701297e99dd9SToby Isaac } 701397e99dd9SToby Isaac } else { 701497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 701597e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 701697e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 701797e99dd9SToby Isaac cind++; 701897e99dd9SToby Isaac } 7019a5e93ea8SMatthew G. Knepley } 7020a5e93ea8SMatthew G. Knepley } 7021a5e93ea8SMatthew G. Knepley } 7022a5e93ea8SMatthew G. Knepley } 70233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7024a5e93ea8SMatthew G. Knepley } 7025a5e93ea8SMatthew G. Knepley 7026d71ae5a4SJacob 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[]) 7027d71ae5a4SJacob Faibussowitsch { 7028552f7358SJed Brown PetscScalar *a; 70291a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 70301a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 703197e99dd9SToby Isaac PetscInt cind = 0, b; 7032552f7358SJed Brown 7033552f7358SJed Brown PetscFunctionBegin; 70349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 70369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 70371a271a75SMatthew G. Knepley a = &array[foff]; 7038552f7358SJed Brown if (!fcdof || setBC) { 703997e99dd9SToby Isaac if (clperm) { 70409371c9d4SSatish Balay if (perm) { 7041ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7042552f7358SJed Brown } else { 7043ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 70449371c9d4SSatish Balay } 70459371c9d4SSatish Balay } else { 70469371c9d4SSatish Balay if (perm) { 7047ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 70489371c9d4SSatish Balay } else { 7049ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 70509371c9d4SSatish Balay } 7051552f7358SJed Brown } 7052552f7358SJed Brown } else { 70539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 705497e99dd9SToby Isaac if (clperm) { 705597e99dd9SToby Isaac if (perm) { 705697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70579371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70589371c9d4SSatish Balay ++cind; 70599371c9d4SSatish Balay continue; 70609371c9d4SSatish Balay } 706197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7062552f7358SJed Brown } 7063552f7358SJed Brown } else { 706497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70659371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70669371c9d4SSatish Balay ++cind; 70679371c9d4SSatish Balay continue; 70689371c9d4SSatish Balay } 706997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 707097e99dd9SToby Isaac } 707197e99dd9SToby Isaac } 707297e99dd9SToby Isaac } else { 707397e99dd9SToby Isaac if (perm) { 707497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70759371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70769371c9d4SSatish Balay ++cind; 70779371c9d4SSatish Balay continue; 70789371c9d4SSatish Balay } 707997e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 708097e99dd9SToby Isaac } 708197e99dd9SToby Isaac } else { 708297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70839371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70849371c9d4SSatish Balay ++cind; 70859371c9d4SSatish Balay continue; 70869371c9d4SSatish Balay } 708797e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7088552f7358SJed Brown } 7089552f7358SJed Brown } 7090552f7358SJed Brown } 7091552f7358SJed Brown } 70921a271a75SMatthew G. Knepley *offset += fdof; 70933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7094552f7358SJed Brown } 7095552f7358SJed Brown 7096d71ae5a4SJacob 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[]) 7097d71ae5a4SJacob Faibussowitsch { 7098a5e93ea8SMatthew G. Knepley PetscScalar *a; 70991a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 71001a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 71015da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 7102ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 7103a5e93ea8SMatthew G. Knepley 7104a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 71059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 71069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 71089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 71091a271a75SMatthew G. Knepley a = &array[foff]; 7110a5e93ea8SMatthew G. Knepley if (fcdof) { 7111ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 71129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 711397e99dd9SToby Isaac if (clperm) { 711497e99dd9SToby Isaac if (perm) { 7115ba322698SMatthew G. Knepley if (comps) { 7116ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7117ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71189371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71199371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71209371c9d4SSatish Balay ncSet = PETSC_TRUE; 71219371c9d4SSatish Balay } 71229371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71239371c9d4SSatish Balay ++cind; 71249371c9d4SSatish Balay fcSet = PETSC_TRUE; 71259371c9d4SSatish Balay } 7126ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7127ba322698SMatthew G. Knepley } 7128ba322698SMatthew G. Knepley } else { 712997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 713097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 713197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7132a5e93ea8SMatthew G. Knepley ++cind; 7133a5e93ea8SMatthew G. Knepley } 7134a5e93ea8SMatthew G. Knepley } 7135ba322698SMatthew G. Knepley } 7136ba322698SMatthew G. Knepley } else { 7137ba322698SMatthew G. Knepley if (comps) { 7138ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7139ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71409371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71419371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71429371c9d4SSatish Balay ncSet = PETSC_TRUE; 71439371c9d4SSatish Balay } 71449371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71459371c9d4SSatish Balay ++cind; 71469371c9d4SSatish Balay fcSet = PETSC_TRUE; 71479371c9d4SSatish Balay } 7148ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 7149ba322698SMatthew G. Knepley } 7150a5e93ea8SMatthew G. Knepley } else { 715197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 715297e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 715397e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 715497e99dd9SToby Isaac ++cind; 715597e99dd9SToby Isaac } 715697e99dd9SToby Isaac } 715797e99dd9SToby Isaac } 7158ba322698SMatthew G. Knepley } 715997e99dd9SToby Isaac } else { 716097e99dd9SToby Isaac if (perm) { 7161ba322698SMatthew G. Knepley if (comps) { 7162ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7163ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71649371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71659371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71669371c9d4SSatish Balay ncSet = PETSC_TRUE; 71679371c9d4SSatish Balay } 71689371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71699371c9d4SSatish Balay ++cind; 71709371c9d4SSatish Balay fcSet = PETSC_TRUE; 71719371c9d4SSatish Balay } 7172ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 7173ba322698SMatthew G. Knepley } 7174ba322698SMatthew G. Knepley } else { 717597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 717697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 717797e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 717897e99dd9SToby Isaac ++cind; 717997e99dd9SToby Isaac } 718097e99dd9SToby Isaac } 7181ba322698SMatthew G. Knepley } 7182ba322698SMatthew G. Knepley } else { 7183ba322698SMatthew G. Knepley if (comps) { 7184ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7185ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71869371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71879371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71889371c9d4SSatish Balay ncSet = PETSC_TRUE; 71899371c9d4SSatish Balay } 71909371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71919371c9d4SSatish Balay ++cind; 71929371c9d4SSatish Balay fcSet = PETSC_TRUE; 71939371c9d4SSatish Balay } 7194ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7195ba322698SMatthew G. Knepley } 719697e99dd9SToby Isaac } else { 719797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 719897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 719997e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7200a5e93ea8SMatthew G. Knepley ++cind; 7201a5e93ea8SMatthew G. Knepley } 7202a5e93ea8SMatthew G. Knepley } 7203a5e93ea8SMatthew G. Knepley } 7204a5e93ea8SMatthew G. Knepley } 7205a5e93ea8SMatthew G. Knepley } 7206ba322698SMatthew G. Knepley } 72071a271a75SMatthew G. Knepley *offset += fdof; 72083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7209a5e93ea8SMatthew G. Knepley } 7210a5e93ea8SMatthew G. Knepley 7211d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7212d71ae5a4SJacob Faibussowitsch { 7213552f7358SJed Brown PetscScalar *array; 72141b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 72151b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 7216552f7358SJed Brown 72171b406b76SMatthew G. Knepley PetscFunctionBeginHot; 72189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 72199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 72209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 72219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 72229566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7223b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 7224b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 7225b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 7226b6ebb6e6SMatthew G. Knepley 72279371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 72289371c9d4SSatish Balay dof = 0; 72299371c9d4SSatish Balay continue; 72309371c9d4SSatish Balay } 72319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 7232b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 7233b6ebb6e6SMatthew G. Knepley { 7234b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7235b6ebb6e6SMatthew G. Knepley PetscScalar *a; 7236b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 7237b6ebb6e6SMatthew G. Knepley 72389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 72399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 7240b6ebb6e6SMatthew G. Knepley a = &array[coff]; 7241b6ebb6e6SMatthew G. Knepley if (!cdof) { 7242b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7243ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 7244b6ebb6e6SMatthew G. Knepley } else { 7245ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 7246b6ebb6e6SMatthew G. Knepley } 7247b6ebb6e6SMatthew G. Knepley } else { 72489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 7249b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7250b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 72519371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 72529371c9d4SSatish Balay ++cind; 72539371c9d4SSatish Balay continue; 72549371c9d4SSatish Balay } 7255b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 7256b6ebb6e6SMatthew G. Knepley } 7257b6ebb6e6SMatthew G. Knepley } else { 7258b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 72599371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 72609371c9d4SSatish Balay ++cind; 72619371c9d4SSatish Balay continue; 72629371c9d4SSatish Balay } 7263b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 7264b6ebb6e6SMatthew G. Knepley } 7265b6ebb6e6SMatthew G. Knepley } 7266b6ebb6e6SMatthew G. Knepley } 7267b6ebb6e6SMatthew G. Knepley } 7268b6ebb6e6SMatthew G. Knepley } 72699566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7271b6ebb6e6SMatthew G. Knepley } 72721b406b76SMatthew G. Knepley 72731b406b76SMatthew G. Knepley /*@C 727420f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 72751b406b76SMatthew G. Knepley 72761b406b76SMatthew G. Knepley Not collective 72771b406b76SMatthew G. Knepley 72781b406b76SMatthew G. Knepley Input Parameters: 7279a1cb98faSBarry Smith + dm - The `DM` 728020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 72811b406b76SMatthew G. Knepley . v - The local vector 728220f4b53cSBarry Smith . point - The point in the `DM` 72831b406b76SMatthew G. Knepley . values - The array of values 7284a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 7285a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 72861b406b76SMatthew G. Knepley 72871b406b76SMatthew G. Knepley Level: intermediate 72881b406b76SMatthew G. Knepley 7289f13dfd9eSBarry Smith Note: 7290f13dfd9eSBarry Smith Usually the input arrays were obtained with `DMPlexVecGetClosure()` 7291f13dfd9eSBarry Smith 72921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 72931b406b76SMatthew G. Knepley @*/ 7294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7295d71ae5a4SJacob Faibussowitsch { 72961b406b76SMatthew G. Knepley PetscSection clSection; 72971b406b76SMatthew G. Knepley IS clPoints; 72981b406b76SMatthew G. Knepley PetscScalar *array; 72991b406b76SMatthew G. Knepley PetscInt *points = NULL; 730027f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 7301c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 73021b406b76SMatthew G. Knepley 73031a271a75SMatthew G. Knepley PetscFunctionBeginHot; 73041b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73059566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 73061a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 73071a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 73089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 73099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 73101b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 73119566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 73123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73131b406b76SMatthew G. Knepley } 73141a271a75SMatthew G. Knepley /* Get points */ 731507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7316c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 7317c459fbc1SJed Brown PetscInt dof; 73189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7319c459fbc1SJed Brown clsize += dof; 7320c459fbc1SJed Brown } 73219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 73221a271a75SMatthew G. Knepley /* Get array */ 73239566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 73241a271a75SMatthew G. Knepley /* Get values */ 7325ef90cfe2SMatthew G. Knepley if (numFields > 0) { 732697e99dd9SToby Isaac PetscInt offset = 0, f; 7327552f7358SJed Brown for (f = 0; f < numFields; ++f) { 732897e99dd9SToby Isaac const PetscInt **perms = NULL; 732997e99dd9SToby Isaac const PetscScalar **flips = NULL; 733097e99dd9SToby Isaac 73319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7332552f7358SJed Brown switch (mode) { 7333552f7358SJed Brown case INSERT_VALUES: 733497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 733597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 733697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 733797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73383ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 73399371c9d4SSatish Balay } 73409371c9d4SSatish Balay break; 7341552f7358SJed Brown case INSERT_ALL_VALUES: 734297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 734397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 734497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 734597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73463ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 73479371c9d4SSatish Balay } 73489371c9d4SSatish Balay break; 7349a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 735097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 735197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 735297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 735397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73543ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 73559371c9d4SSatish Balay } 73569371c9d4SSatish Balay break; 7357552f7358SJed Brown case ADD_VALUES: 735897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 735997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 736097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 736197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73623ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 73639371c9d4SSatish Balay } 73649371c9d4SSatish Balay break; 7365552f7358SJed Brown case ADD_ALL_VALUES: 736697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 736797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 736897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 736997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73703ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 73719371c9d4SSatish Balay } 73729371c9d4SSatish Balay break; 7373304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 737497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 737597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 737697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 737797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73783ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 73799371c9d4SSatish Balay } 73809371c9d4SSatish Balay break; 7381d71ae5a4SJacob Faibussowitsch default: 7382d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7383552f7358SJed Brown } 73849566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 73851a271a75SMatthew G. Knepley } 7386552f7358SJed Brown } else { 73871a271a75SMatthew G. Knepley PetscInt dof, off; 738897e99dd9SToby Isaac const PetscInt **perms = NULL; 738997e99dd9SToby Isaac const PetscScalar **flips = NULL; 73901a271a75SMatthew G. Knepley 73919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7392552f7358SJed Brown switch (mode) { 7393552f7358SJed Brown case INSERT_VALUES: 739497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 739597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 739697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 739797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 73993ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 74009371c9d4SSatish Balay } 74019371c9d4SSatish Balay break; 7402552f7358SJed Brown case INSERT_ALL_VALUES: 740397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 740497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 740597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 740697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74083ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 74099371c9d4SSatish Balay } 74109371c9d4SSatish Balay break; 7411a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 741297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 741397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 741497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 741597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74173ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 74189371c9d4SSatish Balay } 74199371c9d4SSatish Balay break; 7420552f7358SJed Brown case ADD_VALUES: 742197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 742297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 742397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 742497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74263ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 74279371c9d4SSatish Balay } 74289371c9d4SSatish Balay break; 7429552f7358SJed Brown case ADD_ALL_VALUES: 743097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 743197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 743297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 743397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74353ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 74369371c9d4SSatish Balay } 74379371c9d4SSatish Balay break; 7438304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 743997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 744097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 744197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 744297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74443ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 74459371c9d4SSatish Balay } 74469371c9d4SSatish Balay break; 7447d71ae5a4SJacob Faibussowitsch default: 7448d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7449552f7358SJed Brown } 74509566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7451552f7358SJed Brown } 74521a271a75SMatthew G. Knepley /* Cleanup points */ 74539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 74541a271a75SMatthew G. Knepley /* Cleanup array */ 74559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 74563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7457552f7358SJed Brown } 7458552f7358SJed Brown 74595f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7460d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7461d71ae5a4SJacob Faibussowitsch { 74625f790a90SMatthew G. Knepley PetscFunctionBegin; 746311cc89d2SBarry Smith *contains = PETSC_TRUE; 74645f790a90SMatthew G. Knepley if (label) { 7465d6177c40SToby Isaac PetscInt fdof; 74665f790a90SMatthew G. Knepley 746711cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 746811cc89d2SBarry Smith if (!*contains) { 74699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74705f790a90SMatthew G. Knepley *offset += fdof; 74713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74725f790a90SMatthew G. Knepley } 74735f790a90SMatthew G. Knepley } 74743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74755f790a90SMatthew G. Knepley } 74765f790a90SMatthew G. Knepley 747797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7478d71ae5a4SJacob 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) 7479d71ae5a4SJacob Faibussowitsch { 7480e07394fbSMatthew G. Knepley PetscSection clSection; 7481e07394fbSMatthew G. Knepley IS clPoints; 7482e07394fbSMatthew G. Knepley PetscScalar *array; 7483e07394fbSMatthew G. Knepley PetscInt *points = NULL; 748497529cf3SJed Brown const PetscInt *clp; 7485e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 748697e99dd9SToby Isaac PetscInt offset = 0, f; 7487e07394fbSMatthew G. Knepley 7488e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7489e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 74909566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7491e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7492e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 74939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7494e07394fbSMatthew G. Knepley /* Get points */ 749507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7496e07394fbSMatthew G. Knepley /* Get array */ 74979566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7498e07394fbSMatthew G. Knepley /* Get values */ 7499e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 750097e99dd9SToby Isaac const PetscInt **perms = NULL; 750197e99dd9SToby Isaac const PetscScalar **flips = NULL; 750211cc89d2SBarry Smith PetscBool contains; 750397e99dd9SToby Isaac 7504e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7505e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7506e07394fbSMatthew G. Knepley PetscInt fdof; 75079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7508e07394fbSMatthew G. Knepley offset += fdof; 7509e07394fbSMatthew G. Knepley } 7510e07394fbSMatthew G. Knepley continue; 7511e07394fbSMatthew G. Knepley } 75129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7513e07394fbSMatthew G. Knepley switch (mode) { 7514e07394fbSMatthew G. Knepley case INSERT_VALUES: 751597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 751697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 751797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 751897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 751911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 752011cc89d2SBarry Smith if (!contains) continue; 75219566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 75229371c9d4SSatish Balay } 75239371c9d4SSatish Balay break; 7524e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 752597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 752697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 752797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 752897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 752911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 753011cc89d2SBarry Smith if (!contains) continue; 75319566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 75329371c9d4SSatish Balay } 75339371c9d4SSatish Balay break; 7534e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 753597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 753697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 753797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 753897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 753911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 754011cc89d2SBarry Smith if (!contains) continue; 75419566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 75429371c9d4SSatish Balay } 75439371c9d4SSatish Balay break; 7544e07394fbSMatthew G. Knepley case ADD_VALUES: 754597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 754697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 754797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 754897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 754911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 755011cc89d2SBarry Smith if (!contains) continue; 75519566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 75529371c9d4SSatish Balay } 75539371c9d4SSatish Balay break; 7554e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 755597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 755697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 755797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 755897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 755911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 756011cc89d2SBarry Smith if (!contains) continue; 75619566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 75629371c9d4SSatish Balay } 75639371c9d4SSatish Balay break; 7564d71ae5a4SJacob Faibussowitsch default: 7565d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7566e07394fbSMatthew G. Knepley } 75679566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7568e07394fbSMatthew G. Knepley } 7569e07394fbSMatthew G. Knepley /* Cleanup points */ 75709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7571e07394fbSMatthew G. Knepley /* Cleanup array */ 75729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 75733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7574e07394fbSMatthew G. Knepley } 7575e07394fbSMatthew G. Knepley 7576d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7577d71ae5a4SJacob Faibussowitsch { 7578552f7358SJed Brown PetscMPIInt rank; 7579552f7358SJed Brown PetscInt i, j; 7580552f7358SJed Brown 7581552f7358SJed Brown PetscFunctionBegin; 75829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 758363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 758463a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 758563a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7586b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 75873ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7588b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 75899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7590b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7591519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 75929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7593552f7358SJed Brown #else 75949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7595552f7358SJed Brown #endif 7596552f7358SJed Brown } 75979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7598552f7358SJed Brown } 75993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7600552f7358SJed Brown } 7601552f7358SJed Brown 760205586334SMatthew G. Knepley /* 760305586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 760405586334SMatthew G. Knepley 760505586334SMatthew G. Knepley Input Parameters: 760605586334SMatthew G. Knepley + section - The section for this data layout 760736fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 760805586334SMatthew G. Knepley . point - The point contributing dofs with these indices 760905586334SMatthew G. Knepley . off - The global offset of this point 761005586334SMatthew G. Knepley . loff - The local offset of each field 7611a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 761205586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 761305586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 761405586334SMatthew G. Knepley 761505586334SMatthew G. Knepley Output Parameter: 761605586334SMatthew G. Knepley . indices - Indices for dofs on this point 761705586334SMatthew G. Knepley 761805586334SMatthew G. Knepley Level: developer 761905586334SMatthew G. Knepley 762005586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 762105586334SMatthew G. Knepley */ 7622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7623d71ae5a4SJacob Faibussowitsch { 7624e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7625552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7626552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7627552f7358SJed Brown PetscInt cind = 0, k; 7628552f7358SJed Brown 7629552f7358SJed Brown PetscFunctionBegin; 763008401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 76319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 76329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7633552f7358SJed Brown if (!cdof || setBC) { 763405586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 763505586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 763605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 763705586334SMatthew G. Knepley 763805586334SMatthew G. Knepley indices[ind] = off + k; 7639552f7358SJed Brown } 7640552f7358SJed Brown } else { 76419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 76424acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 764305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 764405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 764505586334SMatthew G. Knepley 76464acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 76474acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 764805586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 76494acb8e1eSToby Isaac ++cind; 76504acb8e1eSToby Isaac } else { 765136fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7652552f7358SJed Brown } 7653552f7358SJed Brown } 7654552f7358SJed Brown } 7655e6ccafaeSMatthew G Knepley *loff += dof; 76563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7657552f7358SJed Brown } 7658552f7358SJed Brown 76597e29afd2SMatthew G. Knepley /* 766036fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 76617e29afd2SMatthew G. Knepley 766236fa2b79SJed Brown Input Parameters: 766336fa2b79SJed Brown + section - a section (global or local) 766420f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 766536fa2b79SJed Brown . point - point within section 766636fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 766736fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 766836fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 766936fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 767036fa2b79SJed Brown . permsoff - offset 767136fa2b79SJed Brown - indperm - index permutation 767236fa2b79SJed Brown 767336fa2b79SJed Brown Output Parameter: 767436fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 767536fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 767636fa2b79SJed Brown 767736fa2b79SJed Brown Notes: 767836fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 767936fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 768036fa2b79SJed Brown in the local vector. 768136fa2b79SJed Brown 768236fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 768336fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 768436fa2b79SJed Brown 768536fa2b79SJed Brown Developer Note: 768636fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 768736fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 768836fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 768936fa2b79SJed Brown 769036fa2b79SJed Brown Example: 769136fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 769236fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 769336fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 769436fa2b79SJed 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. 769536fa2b79SJed Brown 769636fa2b79SJed Brown Level: developer 76977e29afd2SMatthew G. Knepley */ 7698d71ae5a4SJacob 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[]) 7699d71ae5a4SJacob Faibussowitsch { 7700552f7358SJed Brown PetscInt numFields, foff, f; 7701552f7358SJed Brown 7702552f7358SJed Brown PetscFunctionBegin; 770308401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 77049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7705552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 77064acb8e1eSToby Isaac PetscInt fdof, cfdof; 7707552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 77084acb8e1eSToby Isaac PetscInt cind = 0, b; 77094acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7710552f7358SJed Brown 77119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 77129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7713552f7358SJed Brown if (!cfdof || setBC) { 771405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 771505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 771605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 771705586334SMatthew G. Knepley 771805586334SMatthew G. Knepley indices[ind] = off + foff + b; 771905586334SMatthew G. Knepley } 7720552f7358SJed Brown } else { 77219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 772205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 772305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 772405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 772505586334SMatthew G. Knepley 77264acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 772705586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7728552f7358SJed Brown ++cind; 7729552f7358SJed Brown } else { 773036fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7731552f7358SJed Brown } 7732552f7358SJed Brown } 7733552f7358SJed Brown } 773436fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7735552f7358SJed Brown foffs[f] += fdof; 7736552f7358SJed Brown } 77373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7738552f7358SJed Brown } 7739552f7358SJed Brown 77407e29afd2SMatthew G. Knepley /* 77417e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 77427e29afd2SMatthew G. Knepley 77437e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7744645102dcSJed Brown 7745645102dcSJed Brown Notes: 7746645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7747645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 77487e29afd2SMatthew G. Knepley */ 7749d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7750d71ae5a4SJacob Faibussowitsch { 77517e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 77527e29afd2SMatthew G. Knepley 77537e29afd2SMatthew G. Knepley PetscFunctionBegin; 77549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 77557e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77567e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 77577e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 77587e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 77597e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 77607e29afd2SMatthew G. Knepley 77619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 77629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 77639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7764645102dcSJed Brown if (!cfdof) { 776505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 776605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 776705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 776805586334SMatthew G. Knepley 776905586334SMatthew G. Knepley indices[ind] = foff + b; 777005586334SMatthew G. Knepley } 77717e29afd2SMatthew G. Knepley } else { 77729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 777305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 777405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 777505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 777605586334SMatthew G. Knepley 77777e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 777805586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 77797e29afd2SMatthew G. Knepley ++cind; 77807e29afd2SMatthew G. Knepley } else { 778105586334SMatthew G. Knepley indices[ind] = foff + b - cind; 77827e29afd2SMatthew G. Knepley } 77837e29afd2SMatthew G. Knepley } 77847e29afd2SMatthew G. Knepley } 77857e29afd2SMatthew G. Knepley foffs[f] += fdof; 77867e29afd2SMatthew G. Knepley } 77873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77887e29afd2SMatthew G. Knepley } 77897e29afd2SMatthew G. Knepley 7790c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms) 7791c789d87fSToby Isaac { 7792c789d87fSToby Isaac PetscInt numFields, sStart, sEnd, cStart, cEnd; 7793c789d87fSToby Isaac 7794c789d87fSToby Isaac PetscFunctionBegin; 7795c789d87fSToby Isaac PetscCall(PetscSectionGetNumFields(section, &numFields)); 7796c789d87fSToby Isaac PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7797c789d87fSToby Isaac PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7798c789d87fSToby Isaac for (PetscInt p = 0; p < nPoints; p++) { 7799c789d87fSToby Isaac PetscInt b = pnts[2 * p]; 7800c789d87fSToby Isaac PetscInt bSecDof = 0, bOff; 7801c789d87fSToby Isaac PetscInt cSecDof = 0; 7802c789d87fSToby Isaac PetscSection indices_section; 7803c789d87fSToby Isaac 7804c789d87fSToby Isaac if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7805c789d87fSToby Isaac if (!bSecDof) continue; 7806c789d87fSToby Isaac if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof)); 7807c789d87fSToby Isaac indices_section = cSecDof > 0 ? cSec : section; 7808c789d87fSToby Isaac if (numFields) { 7809c789d87fSToby Isaac PetscInt fStart[32], fEnd[32]; 7810c789d87fSToby Isaac 7811c789d87fSToby Isaac fStart[0] = 0; 7812c789d87fSToby Isaac fEnd[0] = 0; 7813c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7814c789d87fSToby Isaac PetscInt fDof = 0; 7815c789d87fSToby Isaac 7816c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof)); 7817c789d87fSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7818c789d87fSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7819c789d87fSToby Isaac } 7820c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7821c789d87fSToby Isaac // only apply permutations on one side 7822c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices)); 7823c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7824ac530a7eSPierre Jolivet for (PetscInt i = fStart[f]; i < fEnd[f]; i++) indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7825c789d87fSToby Isaac } 7826c789d87fSToby Isaac } else { 7827c789d87fSToby Isaac PetscInt bEnd = 0; 7828c789d87fSToby Isaac 7829c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7830c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices)); 7831c789d87fSToby Isaac 7832c789d87fSToby Isaac for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7833c789d87fSToby Isaac } 7834c789d87fSToby Isaac } 7835c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7836c789d87fSToby Isaac } 7837c789d87fSToby Isaac 7838c789d87fSToby 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[]) 7839d71ae5a4SJacob Faibussowitsch { 7840d3d1a6afSToby Isaac Mat cMat; 7841d3d1a6afSToby Isaac PetscSection aSec, cSec; 7842d3d1a6afSToby Isaac IS aIS; 7843d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7844a19ea1e9SMatthew G. Knepley PetscInt sStart = -1, sEnd = -1; 7845a19ea1e9SMatthew G. Knepley PetscInt cStart = -1, cEnd = -1; 7846d3d1a6afSToby Isaac const PetscInt *anchors; 7847e969e7a5SJose E. Roman PetscInt numFields, p; 7848d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7849c789d87fSToby Isaac PetscInt *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices; 7850c789d87fSToby Isaac PetscInt oldOffsets[32]; 7851d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7852c789d87fSToby Isaac PetscInt oldOffsetsCopy[32]; 7853c789d87fSToby Isaac PetscInt newOffsetsCopy[32]; 7854c789d87fSToby Isaac PetscScalar *modMat = NULL; 7855d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7856d3d1a6afSToby Isaac 7857d3d1a6afSToby Isaac PetscFunctionBegin; 7858d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7859d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 78609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7861d3d1a6afSToby Isaac 78629566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7863d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7864d3d1a6afSToby Isaac if (aSec) { 78659566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 7866c789d87fSToby Isaac PetscCall(PetscArrayzero(oldOffsets, 32)); 78679566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 78689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7869a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7870d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7871d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7872d3d1a6afSToby Isaac * into the global matrix anyway) */ 7873d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7874d3d1a6afSToby Isaac PetscInt b = points[p]; 7875a19ea1e9SMatthew G. Knepley PetscInt bDof = 0, bSecDof = 0; 7876d3d1a6afSToby Isaac 7877a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7878ad540459SPierre Jolivet if (!bSecDof) continue; 7879c789d87fSToby Isaac 7880c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7881c789d87fSToby Isaac PetscInt fDof = 0; 7882c789d87fSToby Isaac 7883c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7884c789d87fSToby Isaac oldOffsets[f + 1] += fDof; 7885c789d87fSToby Isaac } 788648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7887d3d1a6afSToby Isaac if (bDof) { 7888d3d1a6afSToby Isaac /* this point is constrained */ 7889d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7890d3d1a6afSToby Isaac PetscInt bOff, q; 7891d3d1a6afSToby Isaac 78929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7893d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7894d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7895a19ea1e9SMatthew G. Knepley PetscInt aDof = 0; 7896d3d1a6afSToby Isaac 7897a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7898c789d87fSToby Isaac if (aDof) { 7899c789d87fSToby Isaac anyConstrained = PETSC_TRUE; 7900c789d87fSToby Isaac newNumPoints += 1; 7901c789d87fSToby Isaac } 7902d3d1a6afSToby Isaac newNumIndices += aDof; 7903e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7904a19ea1e9SMatthew G. Knepley PetscInt fDof = 0; 7905d3d1a6afSToby Isaac 7906a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7907d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7908d3d1a6afSToby Isaac } 7909d3d1a6afSToby Isaac } 79109371c9d4SSatish Balay } else { 7911d3d1a6afSToby Isaac /* this point is not constrained */ 7912d3d1a6afSToby Isaac newNumPoints++; 79134b2f2278SToby Isaac newNumIndices += bSecDof; 7914e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7915d3d1a6afSToby Isaac PetscInt fDof; 7916d3d1a6afSToby Isaac 79179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7918d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7919d3d1a6afSToby Isaac } 7920d3d1a6afSToby Isaac } 7921d3d1a6afSToby Isaac } 7922d3d1a6afSToby Isaac } 7923d3d1a6afSToby Isaac if (!anyConstrained) { 792472b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 792572b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 792672b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 7927c789d87fSToby Isaac if (outMat) *outMat = NULL; 79289566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 79293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7930d3d1a6afSToby Isaac } 7931d3d1a6afSToby Isaac 79326ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 79336ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 79346ecaa68aSToby Isaac 7935e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7936e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f]; 7937d3d1a6afSToby Isaac 7938c789d87fSToby Isaac if (!outPoints && !outMat) { 79396ecaa68aSToby Isaac if (offsets) { 7940e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 79416ecaa68aSToby Isaac } 79429566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 79433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79446ecaa68aSToby Isaac } 79456ecaa68aSToby Isaac 79461dca8a05SBarry 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); 7947c789d87fSToby 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); 7948d3d1a6afSToby Isaac 79499566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7950a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7951d3d1a6afSToby Isaac 79526ecaa68aSToby Isaac /* output arrays */ 79539566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 7954c789d87fSToby Isaac PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints)); 79556ecaa68aSToby Isaac 7956c789d87fSToby Isaac // get the new Points 7957c789d87fSToby Isaac for (PetscInt p = 0, newP = 0; p < numPoints; p++) { 7958d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7959c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7960d3d1a6afSToby Isaac 7961a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7962ad540459SPierre Jolivet if (!bSecDof) continue; 796348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7964d3d1a6afSToby Isaac if (bDof) { 79659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7966c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++) { 7967a19ea1e9SMatthew G. Knepley PetscInt a = anchors[bOff + q], aDof = 0; 7968d3d1a6afSToby Isaac 7969a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7970c789d87fSToby Isaac if (aDof) { 7971c789d87fSToby Isaac newPoints[2 * newP] = a; 7972c789d87fSToby Isaac newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation 7973d3d1a6afSToby Isaac newP++; 7974d3d1a6afSToby Isaac } 7975d3d1a6afSToby Isaac } 7976d3d1a6afSToby Isaac } else { 7977d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7978c789d87fSToby Isaac newPoints[2 * newP + 1] = points[2 * p + 1]; 7979d3d1a6afSToby Isaac newP++; 7980d3d1a6afSToby Isaac } 7981d3d1a6afSToby Isaac } 7982d3d1a6afSToby Isaac 7983c789d87fSToby Isaac if (outMat) { 7984c789d87fSToby Isaac PetscScalar *tmpMat; 7985c789d87fSToby Isaac PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32)); 7986c789d87fSToby Isaac PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32)); 7987c789d87fSToby Isaac 7988c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices)); 7989c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7990c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7991c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7992c789d87fSToby Isaac 7993c789d87fSToby Isaac for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1; 7994c789d87fSToby Isaac for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1; 7995c789d87fSToby Isaac 7996c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms)); 7997c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL)); 7998c789d87fSToby Isaac 7999c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 8000c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 8001c789d87fSToby Isaac PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices)); 8002c789d87fSToby Isaac // for each field, insert the anchor modification into modMat 8003c789d87fSToby Isaac for (PetscInt f = 0; f < PetscMax(1, numFields); f++) { 8004c789d87fSToby Isaac PetscInt fStart = oldOffsets[f]; 8005c789d87fSToby Isaac PetscInt fNewStart = newOffsets[f]; 8006e60de12fSPierre Jolivet for (PetscInt p = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) { 8007c789d87fSToby Isaac PetscInt b = points[2 * p]; 8008c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 8009c789d87fSToby Isaac 8010c789d87fSToby Isaac if (b >= sStart && b < sEnd) { 8011d3d1a6afSToby Isaac if (numFields) { 8012c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof)); 80139371c9d4SSatish Balay } else { 8014c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 8015d3d1a6afSToby Isaac } 8016d3d1a6afSToby Isaac } 8017c789d87fSToby Isaac if (!bSecDof) continue; 8018c789d87fSToby Isaac if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 8019c789d87fSToby Isaac if (bDof) { 8020c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 8021e60de12fSPierre Jolivet for (PetscInt q = 0; q < bDof; q++) { 8022c789d87fSToby Isaac PetscInt a = anchors[bOff + q], aDof = 0; 8023d3d1a6afSToby Isaac 8024c789d87fSToby Isaac if (a >= sStart && a < sEnd) { 8025d3d1a6afSToby Isaac if (numFields) { 8026c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 8027c789d87fSToby Isaac } else { 8028c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, a, &aDof)); 8029d3d1a6afSToby Isaac } 8030d3d1a6afSToby Isaac } 8031c789d87fSToby Isaac if (aDof) { 8032c789d87fSToby Isaac PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat)); 8033c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) { 8034c789d87fSToby Isaac for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e]; 8035c789d87fSToby Isaac } 8036c789d87fSToby Isaac } 8037c789d87fSToby Isaac oNew += aDof; 8038c789d87fSToby Isaac } 80399371c9d4SSatish Balay } else { 8040c789d87fSToby Isaac // Insert the identity matrix in this block 8041c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1; 8042c789d87fSToby Isaac oNew += bSecDof; 8043d3d1a6afSToby Isaac } 8044c789d87fSToby Isaac o += bSecDof; 8045d3d1a6afSToby Isaac } 8046d3d1a6afSToby Isaac } 8047d3d1a6afSToby Isaac 8048c789d87fSToby Isaac *outMat = modMat; 80496ecaa68aSToby Isaac 8050c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 8051c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 8052c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 8053c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 8054c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices)); 8055d3d1a6afSToby Isaac } 80569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 8057d3d1a6afSToby Isaac 8058d3d1a6afSToby Isaac /* output */ 80596ecaa68aSToby Isaac if (outPoints) { 8060d3d1a6afSToby Isaac *outPoints = newPoints; 80619371c9d4SSatish Balay } else { 80629566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 80636ecaa68aSToby Isaac } 8064e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 80653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8066d3d1a6afSToby Isaac } 8067d3d1a6afSToby Isaac 8068c789d87fSToby 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) 8069c789d87fSToby Isaac { 8070c789d87fSToby Isaac PetscScalar *modMat = NULL; 8071c789d87fSToby Isaac PetscInt newNumIndices = -1; 80727cd05799SMatthew G. Knepley 8073c789d87fSToby Isaac PetscFunctionBegin; 8074c789d87fSToby 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. 8075c789d87fSToby Isaac modMat is that matrix C */ 8076c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL)); 8077c789d87fSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 8078c789d87fSToby Isaac if (modMat) { 8079c789d87fSToby Isaac const PetscScalar *newValues = values; 80807cd05799SMatthew G. Knepley 8081c789d87fSToby Isaac if (multiplyRight) { 8082c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 80836497c311SBarry Smith PetscBLASInt M, N, K; 8084c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 80857cd05799SMatthew G. Knepley 8086c789d87fSToby 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); 80877cd05799SMatthew G. Knepley 80886497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &M)); 80896497c311SBarry Smith PetscCall(PetscBLASIntCast(numRows, &N)); 80906497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 8091c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues)); 8092c789d87fSToby Isaac // row-major to column-major conversion, right multiplication becomes left multiplication 8093c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M)); 8094c789d87fSToby Isaac numCols = newNumIndices; 8095c789d87fSToby Isaac newValues = newNewValues; 8096c789d87fSToby Isaac } 8097a1cb98faSBarry Smith 8098c789d87fSToby Isaac if (multiplyLeft) { 8099c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 81006497c311SBarry Smith PetscBLASInt M, N, K; 8101c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 81027cd05799SMatthew G. Knepley 8103c789d87fSToby 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); 8104c789d87fSToby Isaac 81056497c311SBarry Smith PetscCall(PetscBLASIntCast(numCols, &M)); 81066497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &N)); 81076497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 8108c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues)); 8109c789d87fSToby Isaac // row-major to column-major conversion, left multiplication becomes right multiplication 8110c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M)); 8111c789d87fSToby Isaac if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues)); 8112c789d87fSToby Isaac newValues = newNewValues; 8113c789d87fSToby Isaac } 8114c789d87fSToby Isaac *outValues = (PetscScalar *)newValues; 8115c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 8116c789d87fSToby Isaac } 8117c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8118c789d87fSToby Isaac } 8119c789d87fSToby Isaac 8120c789d87fSToby 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) 8121c789d87fSToby Isaac { 8122c789d87fSToby Isaac PetscFunctionBegin; 8123c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft)); 8124c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8125c789d87fSToby Isaac } 8126c789d87fSToby Isaac 8127c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize) 8128c789d87fSToby Isaac { 8129c789d87fSToby Isaac /* Closure ordering */ 8130c789d87fSToby Isaac PetscSection clSection; 8131c789d87fSToby Isaac IS clPoints; 8132c789d87fSToby Isaac const PetscInt *clp; 8133c789d87fSToby Isaac PetscInt *points; 8134c789d87fSToby Isaac PetscInt Ncl, Ni = 0; 8135c789d87fSToby Isaac 8136c789d87fSToby Isaac PetscFunctionBeginHot; 8137c789d87fSToby Isaac PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 8138c789d87fSToby Isaac for (PetscInt p = 0; p < Ncl * 2; p += 2) { 8139c789d87fSToby Isaac PetscInt dof; 8140c789d87fSToby Isaac 8141c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, points[p], &dof)); 8142c789d87fSToby Isaac Ni += dof; 8143c789d87fSToby Isaac } 8144c789d87fSToby Isaac PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 8145c789d87fSToby Isaac *closureSize = Ni; 8146c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8147c789d87fSToby Isaac } 8148c789d87fSToby Isaac 8149c789d87fSToby 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) 8150d71ae5a4SJacob Faibussowitsch { 815171f0bbf9SMatthew G. Knepley /* Closure ordering */ 81527773e69fSMatthew G. Knepley PetscSection clSection; 81537773e69fSMatthew G. Knepley IS clPoints; 815471f0bbf9SMatthew G. Knepley const PetscInt *clp; 815571f0bbf9SMatthew G. Knepley PetscInt *points; 815671f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 815771f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 81584acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 815971f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 816071f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 816171f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 816271f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 816371f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 816471f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 816571f0bbf9SMatthew G. Knepley 816671f0bbf9SMatthew G. Knepley PetscInt *idx; 816771f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 816871f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 81697caea556SToby Isaac PetscInt idxStart, idxEnd; 8170c789d87fSToby Isaac PetscInt nRows, nCols; 81717773e69fSMatthew G. Knepley 817271f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 81737773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81747773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 817536fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 8176c789d87fSToby Isaac PetscAssertPointer(numRows, 6); 8177c789d87fSToby Isaac PetscAssertPointer(numCols, 7); 8178c789d87fSToby Isaac if (indices) PetscAssertPointer(indices, 8); 8179c789d87fSToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 9); 8180c789d87fSToby Isaac if (values) PetscAssertPointer(values, 10); 81819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 818263a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 81839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 818471f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 818507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 8186c459fbc1SJed Brown if (useClPerm) { 8187c459fbc1SJed Brown PetscInt depth, clsize; 81889566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 8189c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 8190c459fbc1SJed Brown PetscInt dof; 81919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 8192c459fbc1SJed Brown clsize += dof; 8193c459fbc1SJed Brown } 81949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 8195c459fbc1SJed Brown } 819671f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 819771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 81987773e69fSMatthew G. Knepley PetscInt dof, fdof; 81997773e69fSMatthew G. Knepley 82009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 82017773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 82029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 82037773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 82047773e69fSMatthew G. Knepley } 820571f0bbf9SMatthew G. Knepley Ni += dof; 82067773e69fSMatthew G. Knepley } 8207c789d87fSToby Isaac if (*numRows == -1) *numRows = Ni; 8208c789d87fSToby Isaac if (*numCols == -1) *numCols = Ni; 8209c789d87fSToby Isaac nRows = *numRows; 8210c789d87fSToby Isaac nCols = *numCols; 82117773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 82121dca8a05SBarry 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); 821371f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 8214c789d87fSToby Isaac if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols); 8215c789d87fSToby Isaac if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows); 821671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82179566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 82189566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 821971f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 822071f0bbf9SMatthew G. Knepley if (values && flips[f]) { 822171f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 82226ecaa68aSToby Isaac 822371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 822471f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 822571f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 822671f0bbf9SMatthew G. Knepley 82279566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 82289566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 822971f0bbf9SMatthew G. Knepley if (flip) { 823071f0bbf9SMatthew G. Knepley PetscInt i, j, k; 823171f0bbf9SMatthew G. Knepley 823271f0bbf9SMatthew G. Knepley if (!valCopy) { 82339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 823471f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 823571f0bbf9SMatthew G. Knepley *values = valCopy; 823671f0bbf9SMatthew G. Knepley } 823771f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 823871f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 823971f0bbf9SMatthew G. Knepley 8240c789d87fSToby Isaac if (multiplyRight) { 8241ac530a7eSPierre Jolivet for (k = 0; k < nRows; ++k) valCopy[Ni * k + (foffset + i)] *= fval; 8242c789d87fSToby Isaac } 8243c789d87fSToby Isaac if (multiplyLeft) { 8244ac530a7eSPierre Jolivet for (k = 0; k < nCols; ++k) valCopy[nCols * (foffset + i) + k] *= fval; 82456ecaa68aSToby Isaac } 82466ecaa68aSToby Isaac } 824771f0bbf9SMatthew G. Knepley } 824871f0bbf9SMatthew G. Knepley foffset += fdof; 824971f0bbf9SMatthew G. Knepley } 825071f0bbf9SMatthew G. Knepley } 825171f0bbf9SMatthew G. Knepley } 825271f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 8253c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft)); 825471f0bbf9SMatthew G. Knepley if (NclC) { 825563bfac88SBarry Smith if (multiplyRight) *numCols = NiC; 825663bfac88SBarry Smith if (multiplyLeft) *numRows = NiC; 82579566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 825871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82599566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 82609566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 826171f0bbf9SMatthew G. Knepley } 826271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82639566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 82649566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 826571f0bbf9SMatthew G. Knepley } 82669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 826771f0bbf9SMatthew G. Knepley Ncl = NclC; 826871f0bbf9SMatthew G. Knepley Ni = NiC; 826971f0bbf9SMatthew G. Knepley points = pointsC; 827071f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 827171f0bbf9SMatthew G. Knepley } 827271f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 82739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 82747caea556SToby Isaac PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd)); 827571f0bbf9SMatthew G. Knepley if (Nf) { 827671f0bbf9SMatthew G. Knepley PetscInt idxOff; 827771f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 827871f0bbf9SMatthew G. Knepley 82799371c9d4SSatish Balay if (outOffsets) { 82809371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 82819371c9d4SSatish Balay } 82829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 828371f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 828471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 828571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 828671f0bbf9SMatthew G. Knepley 82879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 82887773e69fSMatthew G. Knepley } 82897773e69fSMatthew G. Knepley } else { 829071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 829171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 829271f0bbf9SMatthew G. Knepley 82937caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 82949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 829571f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 829671f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 829771f0bbf9SMatthew G. Knepley * global section. */ 82989566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 829971f0bbf9SMatthew G. Knepley } 830071f0bbf9SMatthew G. Knepley } 830171f0bbf9SMatthew G. Knepley } else { 830271f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 830371f0bbf9SMatthew G. Knepley 830471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 830571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 83064acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 83074acb8e1eSToby Isaac 83087caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 83099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 831071f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 831171f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 83129566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 83137773e69fSMatthew G. Knepley } 83147773e69fSMatthew G. Knepley } 831571f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 831671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 83179566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 83189566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 83194acb8e1eSToby Isaac } 832071f0bbf9SMatthew G. Knepley if (NclC) { 83219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 83227773e69fSMatthew G. Knepley } else { 83239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 83247773e69fSMatthew G. Knepley } 832571f0bbf9SMatthew G. Knepley 832671f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 83273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 83287773e69fSMatthew G. Knepley } 83297773e69fSMatthew G. Knepley 8330d3d1a6afSToby Isaac /*@C 8331d3d1a6afSToby Isaac DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 8332d3d1a6afSToby Isaac 8333d3d1a6afSToby Isaac Not collective 8334d3d1a6afSToby Isaac 8335d3d1a6afSToby Isaac Input Parameters: 8336d3d1a6afSToby Isaac + dm - The `DM` 8337d3d1a6afSToby Isaac . section - The `PetscSection` describing the points (a local section) 8338d3d1a6afSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 8339d3d1a6afSToby Isaac . point - The point defining the closure 8340d3d1a6afSToby Isaac - useClPerm - Use the closure point permutation if available 8341d3d1a6afSToby Isaac 8342d3d1a6afSToby Isaac Output Parameters: 8343d3d1a6afSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections 8344d3d1a6afSToby Isaac . indices - The dof indices 8345c3871b17SNoam T . outOffsets - Array, of length the number of fields plus 1, to write the field offsets into, or `NULL` 8346d3d1a6afSToby Isaac - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 8347d3d1a6afSToby Isaac 8348d3d1a6afSToby Isaac Level: advanced 8349d3d1a6afSToby Isaac 8350d3d1a6afSToby Isaac Notes: 83512c9a7b26SBarry Smith Call `DMPlexRestoreClosureIndices()` to free allocated memory 8352d3d1a6afSToby Isaac 8353d3d1a6afSToby Isaac If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 8354d3d1a6afSToby Isaac of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 8355d3d1a6afSToby Isaac of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 8356d3d1a6afSToby Isaac indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 8357d3d1a6afSToby Isaac indices (with the above semantics) are implied. 8358d3d1a6afSToby Isaac 8359d3d1a6afSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 8360d3d1a6afSToby Isaac `PetscSection`, `DMGetGlobalSection()` 8361d3d1a6afSToby Isaac @*/ 8362ce78bad3SBarry Smith PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PeOp PetscInt outOffsets[], PeOp PetscScalar *values[]) 8363d3d1a6afSToby Isaac { 8364c789d87fSToby Isaac PetscInt numRows = -1, numCols = -1; 8365d3d1a6afSToby Isaac 8366d3d1a6afSToby Isaac PetscFunctionBeginHot; 8367c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE)); 8368c789d87fSToby Isaac PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols); 8369c789d87fSToby Isaac *numIndices = numRows; 83707773e69fSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 83717773e69fSMatthew G. Knepley } 83727773e69fSMatthew G. Knepley 83737cd05799SMatthew G. Knepley /*@C 837471f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 83757cd05799SMatthew G. Knepley 83767cd05799SMatthew G. Knepley Not collective 83777cd05799SMatthew G. Knepley 83787cd05799SMatthew G. Knepley Input Parameters: 8379a1cb98faSBarry Smith + dm - The `DM` 8380a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8381a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 838271f0bbf9SMatthew G. Knepley . point - The point defining the closure 838371f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 838471f0bbf9SMatthew G. Knepley 838571f0bbf9SMatthew G. Knepley Output Parameters: 838671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 838771f0bbf9SMatthew G. Knepley . indices - The dof indices 838820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 838920f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 839071f0bbf9SMatthew G. Knepley 8391a1cb98faSBarry Smith Level: advanced 839271f0bbf9SMatthew G. Knepley 8393a1cb98faSBarry Smith Notes: 8394a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8395a1cb98faSBarry Smith 8396a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 839771f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 839871f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 839971f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 840071f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 84017cd05799SMatthew G. Knepley 84021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 84037cd05799SMatthew G. Knepley @*/ 8404ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PeOp PetscInt outOffsets[], PeOp PetscScalar *values[]) 8405d71ae5a4SJacob Faibussowitsch { 84067773e69fSMatthew G. Knepley PetscFunctionBegin; 84077773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84084f572ea9SToby Isaac PetscAssertPointer(indices, 7); 84099566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 84103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84117773e69fSMatthew G. Knepley } 84127773e69fSMatthew G. Knepley 8413e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8414d71ae5a4SJacob Faibussowitsch { 8415552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8416552f7358SJed Brown PetscInt *indices; 841771f0bbf9SMatthew G. Knepley PetscInt numIndices; 841871f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8419552f7358SJed Brown PetscErrorCode ierr; 8420552f7358SJed Brown 8421552f7358SJed Brown PetscFunctionBegin; 8422552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84239566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 84243dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 84259566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 84263dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8427e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8428552f7358SJed Brown 8429e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84300d644c17SKarl Rupp 84319566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8432d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 84334a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8434552f7358SJed Brown if (ierr) { 8435552f7358SJed Brown PetscMPIInt rank; 8436552f7358SJed Brown 84379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 84389566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 84399566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 84409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84419566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8442c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8443552f7358SJed Brown } 84444a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 84454a1e0b3eSMatthew G. Knepley PetscInt i; 84469566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 844763a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 84489566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 84494a1e0b3eSMatthew G. Knepley } 845071f0bbf9SMatthew G. Knepley 84519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84529566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 84533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84544acb8e1eSToby Isaac } 845571f0bbf9SMatthew G. Knepley 84564a1e0b3eSMatthew G. Knepley /*@C 8457e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8458e8e188d2SZach Atkins 8459e8e188d2SZach Atkins Not collective 8460e8e188d2SZach Atkins 8461e8e188d2SZach Atkins Input Parameters: 8462e8e188d2SZach Atkins + dm - The `DM` 8463e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8464e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8465e8e188d2SZach Atkins . A - The matrix 8466e8e188d2SZach Atkins . point - The point in the `DM` 8467e8e188d2SZach Atkins . values - The array of values 8468e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8469e8e188d2SZach Atkins 8470e8e188d2SZach Atkins Level: intermediate 8471e8e188d2SZach Atkins 8472e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8473e8e188d2SZach Atkins @*/ 8474e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8475e8e188d2SZach Atkins { 8476e8e188d2SZach Atkins PetscFunctionBegin; 8477e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8478e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8479e8e188d2SZach Atkins } 8480e8e188d2SZach Atkins 8481e8e188d2SZach Atkins /*@C 848260225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 84834a1e0b3eSMatthew G. Knepley 84844a1e0b3eSMatthew G. Knepley Not collective 84854a1e0b3eSMatthew G. Knepley 84864a1e0b3eSMatthew G. Knepley Input Parameters: 8487a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 848820f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8489e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 849020f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8491a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 849220f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8493e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 849420f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 84954a1e0b3eSMatthew G. Knepley . A - The matrix 8496a1cb98faSBarry Smith . point - The point in the `DM` 84974a1e0b3eSMatthew G. Knepley . values - The array of values 8498a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 84994a1e0b3eSMatthew G. Knepley 85004a1e0b3eSMatthew G. Knepley Level: intermediate 85014a1e0b3eSMatthew G. Knepley 85021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 85034a1e0b3eSMatthew G. Knepley @*/ 8504e8e188d2SZach 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) 8505d71ae5a4SJacob Faibussowitsch { 850671f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 850771f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 8508c789d87fSToby Isaac PetscInt numIndicesRow = -1, numIndicesCol = -1; 85097caea556SToby Isaac const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2; 8510c789d87fSToby Isaac 851171f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 851271f0bbf9SMatthew G. Knepley 851371f0bbf9SMatthew G. Knepley PetscFunctionBegin; 851471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 85159566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 851671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 85179566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 851871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8519e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 85209566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8521e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 85229566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8523e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8524e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 852571f0bbf9SMatthew G. Knepley 8526c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow)); 8527c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol)); 85287caea556SToby Isaac valuesV1 = valuesV0; 8529c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE)); 85307caea556SToby Isaac valuesV2 = valuesV1; 8531c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE)); 853271f0bbf9SMatthew G. Knepley 8533c789d87fSToby Isaac if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2)); 8534d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8535c789d87fSToby Isaac ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode); 853671f0bbf9SMatthew G. Knepley if (ierr) { 853771f0bbf9SMatthew G. Knepley PetscMPIInt rank; 853871f0bbf9SMatthew G. Knepley 85399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 85409566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 85419566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 85427caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2)); 85437caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 85447caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 85457caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 8546d3d1a6afSToby Isaac } 854771f0bbf9SMatthew G. Knepley 85487caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2)); 85497caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 85507caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 85517caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 85523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8553552f7358SJed Brown } 8554552f7358SJed Brown 8555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8556d71ae5a4SJacob Faibussowitsch { 8557de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8558de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8559de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8560de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 856117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8562de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8563412e9a14SMatthew G. Knepley DMPolytopeType ct; 85644ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8565de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8566de41b84cSMatthew G. Knepley 8567de41b84cSMatthew G. Knepley PetscFunctionBegin; 8568de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8569de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 85709566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8571de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 85729566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8573de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 85749566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8575de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 85769566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8577de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8578de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 85799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 858063a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 85819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 85829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8583de41b84cSMatthew G. Knepley /* Column indices */ 85849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85854ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8586de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8587de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 85889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8589de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8590de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8591de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8592de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8593de41b84cSMatthew G. Knepley ++q; 8594de41b84cSMatthew G. Knepley } 8595de41b84cSMatthew G. Knepley } 8596de41b84cSMatthew G. Knepley numCPoints = q; 8597de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8598de41b84cSMatthew G. Knepley PetscInt fdof; 8599de41b84cSMatthew G. Knepley 86009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 86014ca5e9f5SMatthew G. Knepley if (!dof) continue; 8602de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 86039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8604de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8605de41b84cSMatthew G. Knepley } 8606de41b84cSMatthew G. Knepley numCIndices += dof; 8607de41b84cSMatthew G. Knepley } 8608de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8609de41b84cSMatthew G. Knepley /* Row indices */ 86109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8611412e9a14SMatthew G. Knepley { 8612012bc364SMatthew G. Knepley DMPlexTransform tr; 8613012bc364SMatthew G. Knepley DMPolytopeType *rct; 8614012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8615012bc364SMatthew G. Knepley 86169566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 86179566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 86189566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8619012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 86209566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8621412e9a14SMatthew G. Knepley } 86229566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8623de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8624de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 86259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8626de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 86279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8628de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8629de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 86309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 86314ca5e9f5SMatthew G. Knepley if (!dof) continue; 86329371c9d4SSatish Balay for (s = 0; s < q; ++s) 86339371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 86344ca5e9f5SMatthew G. Knepley if (s < q) continue; 8635de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8636de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8637de41b84cSMatthew G. Knepley ++q; 8638de41b84cSMatthew G. Knepley } 8639de41b84cSMatthew G. Knepley } 86409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8641de41b84cSMatthew G. Knepley } 8642de41b84cSMatthew G. Knepley numFPoints = q; 8643de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8644de41b84cSMatthew G. Knepley PetscInt fdof; 8645de41b84cSMatthew G. Knepley 86469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 86474ca5e9f5SMatthew G. Knepley if (!dof) continue; 8648de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 86499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8650de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8651de41b84cSMatthew G. Knepley } 8652de41b84cSMatthew G. Knepley numFIndices += dof; 8653de41b84cSMatthew G. Knepley } 8654de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8655de41b84cSMatthew G. Knepley 86561dca8a05SBarry 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); 86571dca8a05SBarry 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); 86589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 86599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8660de41b84cSMatthew G. Knepley if (numFields) { 86614acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 86624acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 86634acb8e1eSToby Isaac 86644acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8667de41b84cSMatthew G. Knepley } 86684acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 86699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86709566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 86714acb8e1eSToby Isaac } 86724acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 86739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86749566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 86754acb8e1eSToby Isaac } 86764acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86779566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86789566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8679de41b84cSMatthew G. Knepley } 8680de41b84cSMatthew G. Knepley } else { 86814acb8e1eSToby Isaac const PetscInt **permsF = NULL; 86824acb8e1eSToby Isaac const PetscInt **permsC = NULL; 86834acb8e1eSToby Isaac 86849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 86859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 86864acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 86874acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 86884acb8e1eSToby Isaac 86899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86909566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8691de41b84cSMatthew G. Knepley } 86924acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 86934acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 86944acb8e1eSToby Isaac 86959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86969566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8697de41b84cSMatthew G. Knepley } 86989566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 86999566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8700de41b84cSMatthew G. Knepley } 87019566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 87024acb8e1eSToby Isaac /* TODO: flips */ 8703d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8704de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8705de41b84cSMatthew G. Knepley if (ierr) { 8706de41b84cSMatthew G. Knepley PetscMPIInt rank; 8707de41b84cSMatthew G. Knepley 87089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 87099566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 87109566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 87119566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 87129566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8713de41b84cSMatthew G. Knepley } 87149566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 87159566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 87169566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 87179566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 87183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8719de41b84cSMatthew G. Knepley } 8720de41b84cSMatthew G. Knepley 8721d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8722d71ae5a4SJacob Faibussowitsch { 87237c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 87247c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8725230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 872617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8727412e9a14SMatthew G. Knepley DMPolytopeType ct; 87287c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 87297c927364SMatthew G. Knepley 87307c927364SMatthew G. Knepley PetscFunctionBegin; 87317c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 87327c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 87339566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 87347c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 87359566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 87367c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 87379566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 87387c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 87399566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 87407c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 87419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 874263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 87437c927364SMatthew G. Knepley /* Column indices */ 87449566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 87457c927364SMatthew G. Knepley maxFPoints = numCPoints; 87467c927364SMatthew G. Knepley /* Compress out points not in the section */ 87477c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 87489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 87497c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 87507c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 87517c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 87527c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 87537c927364SMatthew G. Knepley ++q; 87547c927364SMatthew G. Knepley } 87557c927364SMatthew G. Knepley } 87567c927364SMatthew G. Knepley numCPoints = q; 87577c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 87587c927364SMatthew G. Knepley PetscInt fdof; 87597c927364SMatthew G. Knepley 87609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 87617c927364SMatthew G. Knepley if (!dof) continue; 87627c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 87639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 87647c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 87657c927364SMatthew G. Knepley } 87667c927364SMatthew G. Knepley numCIndices += dof; 87677c927364SMatthew G. Knepley } 87687c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 87697c927364SMatthew G. Knepley /* Row indices */ 87709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8771412e9a14SMatthew G. Knepley { 8772012bc364SMatthew G. Knepley DMPlexTransform tr; 8773012bc364SMatthew G. Knepley DMPolytopeType *rct; 8774012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8775012bc364SMatthew G. Knepley 87769566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 87779566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 87789566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8779012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 87809566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8781412e9a14SMatthew G. Knepley } 87829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 87837c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 87847c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 87859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 87867c927364SMatthew G. Knepley /* Compress out points not in the section */ 87879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 87887c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 87897c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 87909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 87917c927364SMatthew G. Knepley if (!dof) continue; 87929371c9d4SSatish Balay for (s = 0; s < q; ++s) 87939371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 87947c927364SMatthew G. Knepley if (s < q) continue; 87957c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 87967c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 87977c927364SMatthew G. Knepley ++q; 87987c927364SMatthew G. Knepley } 87997c927364SMatthew G. Knepley } 88009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 88017c927364SMatthew G. Knepley } 88027c927364SMatthew G. Knepley numFPoints = q; 88037c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 88047c927364SMatthew G. Knepley PetscInt fdof; 88057c927364SMatthew G. Knepley 88069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 88077c927364SMatthew G. Knepley if (!dof) continue; 88087c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 88099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 88107c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 88117c927364SMatthew G. Knepley } 88127c927364SMatthew G. Knepley numFIndices += dof; 88137c927364SMatthew G. Knepley } 88147c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 88157c927364SMatthew G. Knepley 88161dca8a05SBarry 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); 88171dca8a05SBarry 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); 88187c927364SMatthew G. Knepley if (numFields) { 88194acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 88204acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 88214acb8e1eSToby Isaac 88224acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 88239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 88249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 88257c927364SMatthew G. Knepley } 88264acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 88279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 88289566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 88294acb8e1eSToby Isaac } 88304acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 88319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 88329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 88334acb8e1eSToby Isaac } 88344acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 88359566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 88369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 88377c927364SMatthew G. Knepley } 88387c927364SMatthew G. Knepley } else { 88394acb8e1eSToby Isaac const PetscInt **permsF = NULL; 88404acb8e1eSToby Isaac const PetscInt **permsC = NULL; 88414acb8e1eSToby Isaac 88429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 88439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 88444acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 88454acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 88464acb8e1eSToby Isaac 88479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 88489566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 88497c927364SMatthew G. Knepley } 88504acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 88514acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 88524acb8e1eSToby Isaac 88539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 88549566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 88557c927364SMatthew G. Knepley } 88569566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 88579566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 88587c927364SMatthew G. Knepley } 88599566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 88609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 88613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 88627c927364SMatthew G. Knepley } 88637c927364SMatthew G. Knepley 8864cc4c1da9SBarry Smith /*@ 88657cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 88667cd05799SMatthew G. Knepley 88677cd05799SMatthew G. Knepley Input Parameter: 8868a1cb98faSBarry Smith . dm - The `DMPLEX` object 88697cd05799SMatthew G. Knepley 88707cd05799SMatthew G. Knepley Output Parameter: 88717cd05799SMatthew G. Knepley . cellHeight - The height of a cell 88727cd05799SMatthew G. Knepley 88737cd05799SMatthew G. Knepley Level: developer 88747cd05799SMatthew G. Knepley 88751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 88767cd05799SMatthew G. Knepley @*/ 8877d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8878d71ae5a4SJacob Faibussowitsch { 8879552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8880552f7358SJed Brown 8881552f7358SJed Brown PetscFunctionBegin; 8882552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88834f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8884552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 88853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8886552f7358SJed Brown } 8887552f7358SJed Brown 8888cc4c1da9SBarry Smith /*@ 88897cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 88907cd05799SMatthew G. Knepley 88917cd05799SMatthew G. Knepley Input Parameters: 8892a1cb98faSBarry Smith + dm - The `DMPLEX` object 88937cd05799SMatthew G. Knepley - cellHeight - The height of a cell 88947cd05799SMatthew G. Knepley 88957cd05799SMatthew G. Knepley Level: developer 88967cd05799SMatthew G. Knepley 88971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 88987cd05799SMatthew G. Knepley @*/ 8899d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8900d71ae5a4SJacob Faibussowitsch { 8901552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8902552f7358SJed Brown 8903552f7358SJed Brown PetscFunctionBegin; 8904552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8905552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 89063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8907552f7358SJed Brown } 8908552f7358SJed Brown 8909e6139122SMatthew G. Knepley /*@ 89102827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8911e6139122SMatthew G. Knepley 89122827ebadSStefano Zampini Input Parameters: 89132827ebadSStefano Zampini + dm - The `DMPLEX` object 89142827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8915e6139122SMatthew G. Knepley 8916e6139122SMatthew G. Knepley Output Parameters: 89172827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 89182827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8919e6139122SMatthew G. Knepley 89202a9f31c0SMatthew G. Knepley Level: advanced 8921e6139122SMatthew G. Knepley 89222827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8923e6139122SMatthew G. Knepley @*/ 8924ce78bad3SBarry Smith PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PeOp PetscInt *start, PeOp PetscInt *end) 8925d71ae5a4SJacob Faibussowitsch { 89262827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 89272827ebadSStefano Zampini DMLabel label; 89282827ebadSStefano Zampini PetscInt pStart, pEnd; 8929e6139122SMatthew G. Knepley 8930e6139122SMatthew G. Knepley PetscFunctionBegin; 8931e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89322827ebadSStefano Zampini if (start) { 89334f572ea9SToby Isaac PetscAssertPointer(start, 3); 89342827ebadSStefano Zampini *start = 0; 89352827ebadSStefano Zampini } 89362827ebadSStefano Zampini if (end) { 89374f572ea9SToby Isaac PetscAssertPointer(end, 4); 89382827ebadSStefano Zampini *end = 0; 89392827ebadSStefano Zampini } 89402827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 89412827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 89422827ebadSStefano Zampini if (mesh->tr) { 89432827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 89442827ebadSStefano Zampini } else { 89452827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 89462827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 89472827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 89482827ebadSStefano Zampini } 89493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8950e6139122SMatthew G. Knepley } 8951e6139122SMatthew G. Knepley 895221c42226SMatthew G. Knepley /*@ 895321c42226SMatthew G. Knepley DMPlexGetDepthStratumGlobalSize - Get the global size for a given depth stratum 895421c42226SMatthew G. Knepley 895521c42226SMatthew G. Knepley Input Parameters: 895621c42226SMatthew G. Knepley + dm - The `DMPLEX` object 895721c42226SMatthew G. Knepley - depth - The depth for the given point stratum 895821c42226SMatthew G. Knepley 895921c42226SMatthew G. Knepley Output Parameter: 896021c42226SMatthew G. Knepley . gsize - The global number of points in the stratum 896121c42226SMatthew G. Knepley 896221c42226SMatthew G. Knepley Level: advanced 896321c42226SMatthew G. Knepley 896421c42226SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 896521c42226SMatthew G. Knepley @*/ 896621c42226SMatthew G. Knepley PetscErrorCode DMPlexGetDepthStratumGlobalSize(DM dm, PetscInt depth, PetscInt *gsize) 896721c42226SMatthew G. Knepley { 896821c42226SMatthew G. Knepley PetscSF sf; 896921c42226SMatthew G. Knepley const PetscInt *leaves; 897021c42226SMatthew G. Knepley PetscInt Nl, loc, start, end, lsize = 0; 897121c42226SMatthew G. Knepley 897221c42226SMatthew G. Knepley PetscFunctionBegin; 897321c42226SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 897421c42226SMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 897521c42226SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, depth, &start, &end)); 897621c42226SMatthew G. Knepley for (PetscInt p = start; p < end; ++p) { 897721c42226SMatthew G. Knepley PetscCall(PetscFindInt(p, Nl, leaves, &loc)); 897821c42226SMatthew G. Knepley if (loc < 0) ++lsize; 897921c42226SMatthew G. Knepley } 8980458b0db5SMartin Diehl PetscCallMPI(MPIU_Allreduce(&lsize, gsize, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 898121c42226SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 898221c42226SMatthew G. Knepley } 898321c42226SMatthew G. Knepley 8984d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8985d71ae5a4SJacob Faibussowitsch { 8986552f7358SJed Brown PetscSection section, globalSection; 8987552f7358SJed Brown PetscInt *numbers, p; 8988552f7358SJed Brown 8989552f7358SJed Brown PetscFunctionBegin; 8990d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 89919566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 89929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 899348a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 89949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8995eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 89969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8997552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 89989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8999ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 9000ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 9001552f7358SJed Brown } 90029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 9003ef48cebcSMatthew G. Knepley if (globalSize) { 9004ef48cebcSMatthew G. Knepley PetscLayout layout; 90059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 90069566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 90079566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 9008ef48cebcSMatthew G. Knepley } 90099566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 90109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 90113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9012552f7358SJed Brown } 9013552f7358SJed Brown 9014e2b8d0fcSMatthew G. Knepley /*@ 9015e2b8d0fcSMatthew G. Knepley DMPlexCreateCellNumbering - Get a global cell numbering for all cells on this process 9016e2b8d0fcSMatthew G. Knepley 9017bc9da2b0SJose E. Roman Input Parameters: 9018e2b8d0fcSMatthew G. Knepley + dm - The `DMPLEX` object 9019e2b8d0fcSMatthew G. Knepley - includeAll - Whether to include all cells, or just the simplex and box cells 9020e2b8d0fcSMatthew G. Knepley 9021e2b8d0fcSMatthew G. Knepley Output Parameter: 9022e2b8d0fcSMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 9023e2b8d0fcSMatthew G. Knepley 9024e2b8d0fcSMatthew G. Knepley Level: developer 9025e2b8d0fcSMatthew G. Knepley 9026e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()` 9027e2b8d0fcSMatthew G. Knepley @*/ 9028e2b8d0fcSMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering(DM dm, PetscBool includeAll, IS *globalCellNumbers) 9029d71ae5a4SJacob Faibussowitsch { 9030412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 9031552f7358SJed Brown 9032552f7358SJed Brown PetscFunctionBegin; 90339566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 9034e2b8d0fcSMatthew G. Knepley if (includeAll) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90359566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 90369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 90373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9038552f7358SJed Brown } 903981ed3555SMatthew G. Knepley 90408dab3259SMatthew G. Knepley /*@ 90417cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 90427cd05799SMatthew G. Knepley 90437cd05799SMatthew G. Knepley Input Parameter: 9044a1cb98faSBarry Smith . dm - The `DMPLEX` object 90457cd05799SMatthew G. Knepley 90467cd05799SMatthew G. Knepley Output Parameter: 90477cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 90487cd05799SMatthew G. Knepley 90497cd05799SMatthew G. Knepley Level: developer 90507cd05799SMatthew G. Knepley 9051e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateCellNumbering()`, `DMPlexGetVertexNumbering()` 90527cd05799SMatthew G. Knepley @*/ 9053d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9054d71ae5a4SJacob Faibussowitsch { 905581ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 905681ed3555SMatthew G. Knepley 905781ed3555SMatthew G. Knepley PetscFunctionBegin; 905881ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9059e2b8d0fcSMatthew G. Knepley if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 9060552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 90613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9062552f7358SJed Brown } 9063552f7358SJed Brown 9064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 9065d71ae5a4SJacob Faibussowitsch { 9066412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 906781ed3555SMatthew G. Knepley 906881ed3555SMatthew G. Knepley PetscFunctionBegin; 906981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 90719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 90723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 907381ed3555SMatthew G. Knepley } 907481ed3555SMatthew G. Knepley 90758dab3259SMatthew G. Knepley /*@ 90766aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 90777cd05799SMatthew G. Knepley 90787cd05799SMatthew G. Knepley Input Parameter: 9079a1cb98faSBarry Smith . dm - The `DMPLEX` object 90807cd05799SMatthew G. Knepley 90817cd05799SMatthew G. Knepley Output Parameter: 90827cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 90837cd05799SMatthew G. Knepley 90847cd05799SMatthew G. Knepley Level: developer 90857cd05799SMatthew G. Knepley 90861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 90877cd05799SMatthew G. Knepley @*/ 9088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9089d71ae5a4SJacob Faibussowitsch { 9090552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9091552f7358SJed Brown 9092552f7358SJed Brown PetscFunctionBegin; 9093552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90949566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 9095552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 90963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9097552f7358SJed Brown } 9098552f7358SJed Brown 90998dab3259SMatthew G. Knepley /*@ 9100966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 9101966484cfSJed Brown 910220f4b53cSBarry Smith Collective 91037cd05799SMatthew G. Knepley 91047cd05799SMatthew G. Knepley Input Parameter: 9105a1cb98faSBarry Smith . dm - The `DMPLEX` object 91067cd05799SMatthew G. Knepley 91077cd05799SMatthew G. Knepley Output Parameter: 91087cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 91097cd05799SMatthew G. Knepley 9110a1cb98faSBarry Smith Level: developer 9111966484cfSJed Brown 9112a1cb98faSBarry Smith Notes: 9113a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 9114966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 9115966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 9116966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 9117966484cfSJed Brown 9118966484cfSJed Brown The partitioned mesh is 9119966484cfSJed Brown ``` 9120966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 9121966484cfSJed Brown ``` 9122966484cfSJed Brown and its global numbering is 9123966484cfSJed Brown ``` 9124966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 9125966484cfSJed Brown ``` 9126966484cfSJed Brown Then the global numbering is provided as 9127966484cfSJed Brown ``` 9128966484cfSJed Brown [0] Number of indices in set 5 9129966484cfSJed Brown [0] 0 0 9130966484cfSJed Brown [0] 1 1 9131966484cfSJed Brown [0] 2 3 9132966484cfSJed Brown [0] 3 4 9133966484cfSJed Brown [0] 4 -6 9134966484cfSJed Brown [1] Number of indices in set 3 9135966484cfSJed Brown [1] 0 2 9136966484cfSJed Brown [1] 1 5 9137966484cfSJed Brown [1] 2 6 9138966484cfSJed Brown ``` 9139966484cfSJed Brown 91401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 91417cd05799SMatthew G. Knepley @*/ 9142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 9143d71ae5a4SJacob Faibussowitsch { 9144ef48cebcSMatthew G. Knepley IS nums[4]; 9145862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 9146ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 91470c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 9148ef48cebcSMatthew G. Knepley 9149ef48cebcSMatthew G. Knepley PetscFunctionBegin; 9150ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 91520c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 91539566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 91540c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 9155862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 9156862913ffSStefano Zampini PetscInt end; 9157862913ffSStefano Zampini 9158862913ffSStefano Zampini depths[d] = depth - d; 91599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 91600c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 9161862913ffSStefano Zampini } 91620c15888dSMatthew G. Knepley if (empty) 91630c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 91640c15888dSMatthew G. Knepley depths[d] = -1; 91650c15888dSMatthew G. Knepley starts[d] = -1; 91660c15888dSMatthew G. Knepley } 91670c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 9168e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 9169ad540459SPierre 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]); 91700c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 9171ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 9172ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 9173ef48cebcSMatthew G. Knepley 91749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 91759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 9176ef48cebcSMatthew G. Knepley shift += gsize; 9177ef48cebcSMatthew G. Knepley } 9178d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 91799566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 91803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9181ef48cebcSMatthew G. Knepley } 9182ef48cebcSMatthew G. Knepley 918308a22f4bSMatthew G. Knepley /*@ 9184484edb7dSMatthew G. Knepley DMPlexCreateEdgeNumbering - Create a global numbering for edges. 9185484edb7dSMatthew G. Knepley 9186484edb7dSMatthew G. Knepley Collective 9187484edb7dSMatthew G. Knepley 9188484edb7dSMatthew G. Knepley Input Parameter: 9189484edb7dSMatthew G. Knepley . dm - The `DMPLEX` object 9190484edb7dSMatthew G. Knepley 9191484edb7dSMatthew G. Knepley Output Parameter: 9192484edb7dSMatthew G. Knepley . globalEdgeNumbers - Global numbers for all edges on this process 9193484edb7dSMatthew G. Knepley 9194484edb7dSMatthew G. Knepley Level: developer 9195484edb7dSMatthew G. Knepley 9196484edb7dSMatthew G. Knepley Notes: 9197484edb7dSMatthew G. Knepley The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). In the IS, owned edges will have their non-negative value while edges owned by different ranks will be involuted -(idx+1). 9198484edb7dSMatthew G. Knepley 9199484edb7dSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()`, `DMPlexCreatePointNumbering()` 9200484edb7dSMatthew G. Knepley @*/ 9201484edb7dSMatthew G. Knepley PetscErrorCode DMPlexCreateEdgeNumbering(DM dm, IS *globalEdgeNumbers) 9202484edb7dSMatthew G. Knepley { 9203484edb7dSMatthew G. Knepley PetscSF sf; 9204484edb7dSMatthew G. Knepley PetscInt eStart, eEnd; 9205484edb7dSMatthew G. Knepley 9206484edb7dSMatthew G. Knepley PetscFunctionBegin; 9207484edb7dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9208484edb7dSMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 9209484edb7dSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9210484edb7dSMatthew G. Knepley PetscCall(DMPlexCreateNumbering_Plex(dm, eStart, eEnd, 0, NULL, sf, globalEdgeNumbers)); 9211484edb7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 9212484edb7dSMatthew G. Knepley } 9213484edb7dSMatthew G. Knepley 9214484edb7dSMatthew G. Knepley /*@ 921508a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 921608a22f4bSMatthew G. Knepley 921708a22f4bSMatthew G. Knepley Input Parameter: 9218a1cb98faSBarry Smith . dm - The `DMPLEX` object 921908a22f4bSMatthew G. Knepley 922008a22f4bSMatthew G. Knepley Output Parameter: 922108a22f4bSMatthew G. Knepley . ranks - The rank field 922208a22f4bSMatthew G. Knepley 9223a1cb98faSBarry Smith Options Database Key: 922420f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 922508a22f4bSMatthew G. Knepley 922608a22f4bSMatthew G. Knepley Level: intermediate 922708a22f4bSMatthew G. Knepley 92281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 922908a22f4bSMatthew G. Knepley @*/ 9230d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 9231d71ae5a4SJacob Faibussowitsch { 923208a22f4bSMatthew G. Knepley DM rdm; 923308a22f4bSMatthew G. Knepley PetscFE fe; 923408a22f4bSMatthew G. Knepley PetscScalar *r; 923508a22f4bSMatthew G. Knepley PetscMPIInt rank; 9236a55f9a55SMatthew G. Knepley DMPolytopeType ct; 923708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 9238a55f9a55SMatthew G. Knepley PetscBool simplex; 923908a22f4bSMatthew G. Knepley 924008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 9241f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92424f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 92439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 92449566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 92459566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 92469566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 92479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 9248a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 92499566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 92509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 92519566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 92529566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 92539566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 92549566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 92559566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 92569566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 925708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 925808a22f4bSMatthew G. Knepley PetscScalar *lr; 925908a22f4bSMatthew G. Knepley 92609566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 926171f09efeSPierre Jolivet if (lr) *lr = rank; 926208a22f4bSMatthew G. Knepley } 92639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 92649566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 92653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 926608a22f4bSMatthew G. Knepley } 926708a22f4bSMatthew G. Knepley 9268ca8062c8SMatthew G. Knepley /*@ 9269acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 927018e14f0cSMatthew G. Knepley 927118e14f0cSMatthew G. Knepley Input Parameters: 927220f4b53cSBarry Smith + dm - The `DMPLEX` 927320f4b53cSBarry Smith - label - The `DMLabel` 927418e14f0cSMatthew G. Knepley 927518e14f0cSMatthew G. Knepley Output Parameter: 927618e14f0cSMatthew G. Knepley . val - The label value field 927718e14f0cSMatthew G. Knepley 927820f4b53cSBarry Smith Options Database Key: 927920f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 928018e14f0cSMatthew G. Knepley 928118e14f0cSMatthew G. Knepley Level: intermediate 928218e14f0cSMatthew G. Knepley 92831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 928418e14f0cSMatthew G. Knepley @*/ 9285d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 9286d71ae5a4SJacob Faibussowitsch { 92871033741fSStefano Zampini DM rdm, plex; 9288acf3173eSStefano Zampini Vec lval; 9289acf3173eSStefano Zampini PetscSection section; 929018e14f0cSMatthew G. Knepley PetscFE fe; 929118e14f0cSMatthew G. Knepley PetscScalar *v; 9292acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 9293acf3173eSStefano Zampini DMPolytopeType ct; 9294acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 9295acf3173eSStefano Zampini const char *lname, *prefix; 929618e14f0cSMatthew G. Knepley 929718e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 929818e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92994f572ea9SToby Isaac PetscAssertPointer(label, 2); 93004f572ea9SToby Isaac PetscAssertPointer(val, 3); 93019566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 9302acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 9303acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 9304acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 9305acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 93069566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 9307acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 9308acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 9309acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 9310acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 9311acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 93129566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 93139566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 93149566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 93159566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 9316acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 9317acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 9318acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 9319acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 9320acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 9321acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 9322acf3173eSStefano Zampini PetscInt cval, dof, off; 932318e14f0cSMatthew G. Knepley 9324acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 9325acf3173eSStefano Zampini if (!dof) continue; 9326acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 9327acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 9328acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 932918e14f0cSMatthew G. Knepley } 9330acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 9331acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 9332acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 93339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 93343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 933518e14f0cSMatthew G. Knepley } 933618e14f0cSMatthew G. Knepley 933718e14f0cSMatthew G. Knepley /*@ 9338ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 9339ca8062c8SMatthew G. Knepley 934069916449SMatthew G. Knepley Input Parameter: 9341a1cb98faSBarry Smith . dm - The `DMPLEX` object 9342a1cb98faSBarry Smith 9343a1cb98faSBarry Smith Level: developer 9344ca8062c8SMatthew G. Knepley 934595eb5ee5SVaclav Hapla Notes: 934695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 934795eb5ee5SVaclav Hapla 934820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9349ca8062c8SMatthew G. Knepley 93501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9351ca8062c8SMatthew G. Knepley @*/ 9352d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 9353d71ae5a4SJacob Faibussowitsch { 9354ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 9355ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 9356ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 935757beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 935857beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9359ca8062c8SMatthew G. Knepley 9360ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9361ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93629566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 93639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 93649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9365ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 93669566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9367ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 93689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 93699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9370ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 937142e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 937242e66dfaSMatthew G. Knepley PetscInt d; 937342e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 93749371c9d4SSatish Balay if (cone[c] == cone[d]) { 93759371c9d4SSatish Balay dup = PETSC_TRUE; 93769371c9d4SSatish Balay break; 93779371c9d4SSatish Balay } 937842e66dfaSMatthew G. Knepley } 93799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 93809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9381ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9382ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9383ca8062c8SMatthew G. Knepley } 938442e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 938563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 938648a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 93879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 938863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 938948a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 93909566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 939163a3b9bcSJacob 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]); 9392f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9393ca8062c8SMatthew G. Knepley } 939442e66dfaSMatthew G. Knepley } 93959566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 93969371c9d4SSatish Balay if (p != pp) { 93979371c9d4SSatish Balay storagecheck = PETSC_FALSE; 93989371c9d4SSatish Balay continue; 93999371c9d4SSatish Balay } 94009566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 94019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9402ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 94039566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 94049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9405ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 94069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 94079371c9d4SSatish Balay if (cone[c] != pp) { 94089371c9d4SSatish Balay c = 0; 94099371c9d4SSatish Balay break; 94109371c9d4SSatish Balay } 9411ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9412ca8062c8SMatthew G. Knepley } 9413ca8062c8SMatthew G. Knepley if (c >= coneSize) { 941463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 941548a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 94169566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 941763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 941848a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 94199566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 942063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9421ca8062c8SMatthew G. Knepley } 9422ca8062c8SMatthew G. Knepley } 9423ca8062c8SMatthew G. Knepley } 942457beb4faSStefano Zampini if (storagecheck) { 94259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 94269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 942763a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 942857beb4faSStefano Zampini } 94293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9430ca8062c8SMatthew G. Knepley } 9431ca8062c8SMatthew G. Knepley 9432412e9a14SMatthew G. Knepley /* 9433412e9a14SMatthew 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. 9434412e9a14SMatthew G. Knepley */ 9435d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9436d71ae5a4SJacob Faibussowitsch { 9437412e9a14SMatthew G. Knepley DMPolytopeType cct; 9438412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9439412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9440412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9441412e9a14SMatthew G. Knepley 9442412e9a14SMatthew G. Knepley PetscFunctionBegin; 9443412e9a14SMatthew G. Knepley *unsplit = 0; 9444412e9a14SMatthew G. Knepley switch (ct) { 9445d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9446d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9447d71ae5a4SJacob Faibussowitsch break; 9448412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 94499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 94509566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9451412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 94529566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9453412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9454412e9a14SMatthew G. Knepley } 9455412e9a14SMatthew G. Knepley break; 9456412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9457412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 94589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 94599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9460412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 94619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 94629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9463412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 94649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9465412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9466412e9a14SMatthew G. Knepley PetscInt p; 94679371c9d4SSatish Balay for (p = 0; p < npt; ++p) 94689371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9469412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9470412e9a14SMatthew G. Knepley } 9471412e9a14SMatthew G. Knepley } 9472412e9a14SMatthew G. Knepley } 9473412e9a14SMatthew G. Knepley break; 9474d71ae5a4SJacob Faibussowitsch default: 9475d71ae5a4SJacob Faibussowitsch break; 9476412e9a14SMatthew G. Knepley } 9477412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 94789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9479412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9480412e9a14SMatthew G. Knepley } 94813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9482412e9a14SMatthew G. Knepley } 9483412e9a14SMatthew G. Knepley 9484ca8062c8SMatthew G. Knepley /*@ 9485ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9486ca8062c8SMatthew G. Knepley 9487ca8062c8SMatthew G. Knepley Input Parameters: 9488a1cb98faSBarry Smith + dm - The `DMPLEX` object 948958723a97SMatthew G. Knepley - cellHeight - Normally 0 9490ca8062c8SMatthew G. Knepley 9491a1cb98faSBarry Smith Level: developer 9492a1cb98faSBarry Smith 949395eb5ee5SVaclav Hapla Notes: 949495eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 949525c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9496ca8062c8SMatthew G. Knepley 949720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 949895eb5ee5SVaclav Hapla 94991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9500ca8062c8SMatthew G. Knepley @*/ 9501d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9502d71ae5a4SJacob Faibussowitsch { 9503412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9504412e9a14SMatthew G. Knepley DMPolytopeType ct; 9505412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9506ca8062c8SMatthew G. Knepley 9507ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9508ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95099566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 95109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 95119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9512412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9513412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9514412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 951558723a97SMatthew G. Knepley 95169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9517412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9518412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 95199566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 952063a3b9bcSJacob 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)); 9521412e9a14SMatthew G. Knepley } 95229566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 952358723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 952458723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9525412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 952658723a97SMatthew G. Knepley } 95279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9528412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9529412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9530412e9a14SMatthew G. Knepley PetscInt unsplit; 953142363296SMatthew G. Knepley 95329566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9533412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 953442363296SMatthew G. Knepley } 953563a3b9bcSJacob 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)); 953642363296SMatthew G. Knepley } 95373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9538ca8062c8SMatthew G. Knepley } 95399bf0dad6SMatthew G. Knepley 95409bf0dad6SMatthew G. Knepley /*@ 95419bf0dad6SMatthew 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 95429bf0dad6SMatthew G. Knepley 954320f4b53cSBarry Smith Collective 9544899ea2b8SJacob Faibussowitsch 95459bf0dad6SMatthew G. Knepley Input Parameters: 9546a1cb98faSBarry Smith + dm - The `DMPLEX` object 95479bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 95489bf0dad6SMatthew G. Knepley 9549a1cb98faSBarry Smith Level: developer 9550a1cb98faSBarry Smith 955145da879fSVaclav Hapla Notes: 955245da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 955345da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 955445da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 955545da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 95569bf0dad6SMatthew G. Knepley 9557a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 955895eb5ee5SVaclav Hapla 95591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 95609bf0dad6SMatthew G. Knepley @*/ 9561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9562d71ae5a4SJacob Faibussowitsch { 9563ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9564899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 95659bf0dad6SMatthew G. Knepley 95669bf0dad6SMatthew G. Knepley PetscFunctionBegin; 95679bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95688f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 95693ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 95708f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 95713ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 95723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9573899ea2b8SJacob Faibussowitsch } 9574899ea2b8SJacob Faibussowitsch 95759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 95769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 95779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9578ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 95799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 95803554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9581412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9582412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9583ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9584412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9585412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 95869bf0dad6SMatthew G. Knepley 95879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 95889566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9589412e9a14SMatthew G. Knepley if (unsplit) continue; 95909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 95919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 95929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 95939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 95949bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 95959bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 95969bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 95979bf0dad6SMatthew G. Knepley } 95989566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 959963a3b9bcSJacob 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); 96009bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9601d4961f80SStefano Zampini DMPolytopeType fct; 96029bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 96039bf0dad6SMatthew G. Knepley 96049566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 96059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 96069bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 96079bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 96089bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 96099bf0dad6SMatthew G. Knepley } 961063a3b9bcSJacob 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]); 96119bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9612b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9613b5a892a1SMatthew G. Knepley PetscInt v1; 9614b5a892a1SMatthew G. Knepley 96159566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 961663a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 96179566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 961863a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 96199566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 962063a3b9bcSJacob 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]); 9621b5a892a1SMatthew G. Knepley } 96229bf0dad6SMatthew G. Knepley } 96239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9624412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 96259bf0dad6SMatthew G. Knepley } 96269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 96279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 96289bf0dad6SMatthew G. Knepley } 96293554e41dSMatthew G. Knepley } 96303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9631552f7358SJed Brown } 96323913d7c8SMatthew G. Knepley 9633bb6a34a8SMatthew G. Knepley /*@ 9634bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9635bb6a34a8SMatthew G. Knepley 9636bb6a34a8SMatthew G. Knepley Input Parameter: 9637a1cb98faSBarry Smith . dm - The `DMPLEX` object 9638a1cb98faSBarry Smith 9639a1cb98faSBarry Smith Level: developer 9640bb6a34a8SMatthew G. Knepley 964195eb5ee5SVaclav Hapla Notes: 964295eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 964395eb5ee5SVaclav Hapla 964420f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9645bb6a34a8SMatthew G. Knepley 96461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9647bb6a34a8SMatthew G. Knepley @*/ 9648d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9649d71ae5a4SJacob Faibussowitsch { 9650a2a9e04cSMatthew G. Knepley Vec coordinates; 9651bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9652bb6a34a8SMatthew G. Knepley PetscReal vol; 965351a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9654bb6a34a8SMatthew G. Knepley 9655bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 96569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 96579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 96583ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 96599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9660bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 96619566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9662a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 96639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 96643ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9665412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9666412e9a14SMatthew G. Knepley DMPolytopeType ct; 9667412e9a14SMatthew G. Knepley PetscInt unsplit; 9668412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9669412e9a14SMatthew G. Knepley 96709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9671412e9a14SMatthew G. Knepley switch (ct) { 9672412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9673412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9674d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9675d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9676d71ae5a4SJacob Faibussowitsch break; 9677d71ae5a4SJacob Faibussowitsch default: 9678d71ae5a4SJacob Faibussowitsch break; 9679412e9a14SMatthew G. Knepley } 9680412e9a14SMatthew G. Knepley switch (ct) { 9681412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9682412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9683412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9684d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9685d71ae5a4SJacob Faibussowitsch continue; 9686d71ae5a4SJacob Faibussowitsch default: 9687d71ae5a4SJacob Faibussowitsch break; 9688412e9a14SMatthew G. Knepley } 96899566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9690412e9a14SMatthew G. Knepley if (unsplit) continue; 96919566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 96921dca8a05SBarry 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); 969363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 96946858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 96956858538eSMatthew G. Knepley if (depth > 1) { 96969566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 96971dca8a05SBarry 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); 969863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9699bb6a34a8SMatthew G. Knepley } 9700bb6a34a8SMatthew G. Knepley } 97013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9702bb6a34a8SMatthew G. Knepley } 9703bb6a34a8SMatthew G. Knepley 970403da9461SVaclav Hapla /*@ 970520f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 97067726db96SVaclav Hapla 970720f4b53cSBarry Smith Collective 970803da9461SVaclav Hapla 970903da9461SVaclav Hapla Input Parameters: 9710a1cb98faSBarry Smith + dm - The `DMPLEX` object 971120f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9712a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9713a1cb98faSBarry Smith 9714a1cb98faSBarry Smith Level: developer 971503da9461SVaclav Hapla 9716e83a0d2dSVaclav Hapla Notes: 9717e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 971803da9461SVaclav Hapla 9719a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 972095eb5ee5SVaclav Hapla 9721baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9722d7d32a9aSMatthew G. Knepley 97231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 972403da9461SVaclav Hapla @*/ 9725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9726d71ae5a4SJacob Faibussowitsch { 97277726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 97287726db96SVaclav Hapla const PetscInt *locals; 97297726db96SVaclav Hapla const PetscSFNode *remotes; 9730f0cfc026SVaclav Hapla PetscBool distributed; 97317726db96SVaclav Hapla MPI_Comm comm; 97327726db96SVaclav Hapla PetscMPIInt rank; 973303da9461SVaclav Hapla 973403da9461SVaclav Hapla PetscFunctionBegin; 973503da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97367726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 97377726db96SVaclav Hapla else pointSF = dm->sf; 97387726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 97397726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 97407726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 97417726db96SVaclav Hapla { 97427726db96SVaclav Hapla PetscMPIInt mpiFlag; 97437726db96SVaclav Hapla 97447726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 97457726db96SVaclav 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); 97467726db96SVaclav Hapla } 97477726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 97489566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 97497726db96SVaclav Hapla if (!distributed) { 97507726db96SVaclav 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); 97513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97528918e3e2SVaclav Hapla } 97537726db96SVaclav 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); 97547726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 975503da9461SVaclav Hapla 97567726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 97577726db96SVaclav Hapla { 97587726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 97597726db96SVaclav Hapla 97607726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 97617726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9762d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 97637726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 97647726db96SVaclav Hapla } 97657726db96SVaclav Hapla 97667726db96SVaclav Hapla /* Check there are no cells in interface */ 97677726db96SVaclav Hapla if (!overlap) { 97687726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 97697726db96SVaclav Hapla 97709566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97719566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9772f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 97737726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9774f5869d18SMatthew G. Knepley 97757726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 97767726db96SVaclav Hapla } 977703da9461SVaclav Hapla } 9778ece87651SVaclav Hapla 97797726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 97807726db96SVaclav Hapla { 97817726db96SVaclav Hapla const PetscInt *rootdegree; 97827726db96SVaclav Hapla 97837726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 97847726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9785f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 97867726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9787f5869d18SMatthew G. Knepley const PetscInt *cone; 9788f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9789f5869d18SMatthew G. Knepley 97909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 97919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9792f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9793f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 97947726db96SVaclav Hapla if (locals) { 97959566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 97967726db96SVaclav Hapla } else { 97977726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 97987726db96SVaclav Hapla } 979963a3b9bcSJacob 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]); 9800f5869d18SMatthew G. Knepley } 9801f5869d18SMatthew G. Knepley } 9802ece87651SVaclav Hapla } 98037726db96SVaclav Hapla } 98043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 980503da9461SVaclav Hapla } 980603da9461SVaclav Hapla 98077f9d8d6cSVaclav Hapla /*@ 9808217fe35eSMatthew G. Knepley DMPlexCheckOrphanVertices - Check that no vertices are disconnected from the mesh, unless the mesh only consists of disconnected vertices. 9809217fe35eSMatthew G. Knepley 9810217fe35eSMatthew G. Knepley Collective 9811217fe35eSMatthew G. Knepley 9812217fe35eSMatthew G. Knepley Input Parameter: 9813217fe35eSMatthew G. Knepley . dm - The `DMPLEX` object 9814217fe35eSMatthew G. Knepley 9815217fe35eSMatthew G. Knepley Level: developer 9816217fe35eSMatthew G. Knepley 9817217fe35eSMatthew G. Knepley Notes: 9818217fe35eSMatthew G. Knepley This is mainly intended for debugging/testing purposes. 9819217fe35eSMatthew G. Knepley 9820217fe35eSMatthew G. Knepley Other cell types which are disconnected would be caught by the symmetry and face checks. 9821217fe35eSMatthew G. Knepley 9822217fe35eSMatthew G. Knepley For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9823217fe35eSMatthew G. Knepley 9824217fe35eSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheck()`, `DMSetFromOptions()` 9825217fe35eSMatthew G. Knepley @*/ 9826217fe35eSMatthew G. Knepley PetscErrorCode DMPlexCheckOrphanVertices(DM dm) 9827217fe35eSMatthew G. Knepley { 9828217fe35eSMatthew G. Knepley PetscInt pStart, pEnd, vStart, vEnd; 9829217fe35eSMatthew G. Knepley 9830217fe35eSMatthew G. Knepley PetscFunctionBegin; 9831217fe35eSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9832217fe35eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9833217fe35eSMatthew G. Knepley if (pStart == vStart && pEnd == vEnd) PetscFunctionReturn(PETSC_SUCCESS); 9834217fe35eSMatthew G. Knepley for (PetscInt v = vStart; v < vEnd; ++v) { 9835217fe35eSMatthew G. Knepley PetscInt suppSize; 9836217fe35eSMatthew G. Knepley 9837217fe35eSMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, v, &suppSize)); 9838217fe35eSMatthew G. Knepley PetscCheck(suppSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is disconnected from the mesh", v); 9839217fe35eSMatthew G. Knepley } 9840217fe35eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 9841217fe35eSMatthew G. Knepley } 9842217fe35eSMatthew G. Knepley 9843217fe35eSMatthew G. Knepley /*@ 984420f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 98457f9d8d6cSVaclav Hapla 98467f9d8d6cSVaclav Hapla Input Parameter: 9847a1cb98faSBarry Smith . dm - The `DMPLEX` object 9848a1cb98faSBarry Smith 9849a1cb98faSBarry Smith Level: developer 98507f9d8d6cSVaclav Hapla 98517f9d8d6cSVaclav Hapla Notes: 98527f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 98537f9d8d6cSVaclav Hapla 985420f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 98557f9d8d6cSVaclav Hapla 985620f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 98577f9d8d6cSVaclav Hapla 98581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 98597f9d8d6cSVaclav Hapla @*/ 9860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9861d71ae5a4SJacob Faibussowitsch { 98627f9d8d6cSVaclav Hapla PetscInt cellHeight; 98637f9d8d6cSVaclav Hapla 9864b5a892a1SMatthew G. Knepley PetscFunctionBegin; 98657f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 98669566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 98679566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 98689566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 98699566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9870d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 98719566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 9872217fe35eSMatthew G. Knepley PetscCall(DMPlexCheckOrphanVertices(dm)); 98733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9874b5a892a1SMatthew G. Knepley } 9875b5a892a1SMatthew G. Knepley 98769371c9d4SSatish Balay typedef struct cell_stats { 9877068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9878068a5610SStefano Zampini PetscInt count; 9879068a5610SStefano Zampini } cell_stats_t; 9880068a5610SStefano Zampini 9881d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9882d71ae5a4SJacob Faibussowitsch { 9883068a5610SStefano Zampini PetscInt i, N = *len; 9884068a5610SStefano Zampini 9885068a5610SStefano Zampini for (i = 0; i < N; i++) { 9886068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9887068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9888068a5610SStefano Zampini 9889068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9890068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9891068a5610SStefano Zampini B->sum += A->sum; 9892068a5610SStefano Zampini B->squaresum += A->squaresum; 9893068a5610SStefano Zampini B->count += A->count; 9894068a5610SStefano Zampini } 9895068a5610SStefano Zampini } 9896068a5610SStefano Zampini 9897068a5610SStefano Zampini /*@ 989843fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9899068a5610SStefano Zampini 990020f4b53cSBarry Smith Collective 99018261a58bSMatthew G. Knepley 9902068a5610SStefano Zampini Input Parameters: 9903a1cb98faSBarry Smith + dm - The `DMPLEX` object 990420f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9905a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9906a1cb98faSBarry Smith 9907a1cb98faSBarry Smith Level: developer 9908068a5610SStefano Zampini 990995eb5ee5SVaclav Hapla Notes: 991095eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 991195eb5ee5SVaclav Hapla 9912a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9913068a5610SStefano Zampini 99141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9915068a5610SStefano Zampini @*/ 9916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9917d71ae5a4SJacob Faibussowitsch { 9918068a5610SStefano Zampini DM dmCoarse; 991943fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 992043fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 992143fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 992243fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9923412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 992443fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9925068a5610SStefano Zampini 9926068a5610SStefano Zampini PetscFunctionBegin; 9927068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9928068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9929068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9930068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9931068a5610SStefano Zampini stats.count = 0; 9932068a5610SStefano Zampini 99339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 99349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 99359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 99369566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 99379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 99389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9939412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9940068a5610SStefano Zampini PetscInt i; 9941068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9942068a5610SStefano Zampini 99439566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 994463a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 994543fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9946068a5610SStefano Zampini frobJ += J[i] * J[i]; 9947068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9948068a5610SStefano Zampini } 9949068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9950068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9951068a5610SStefano Zampini 9952068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9953068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9954068a5610SStefano Zampini stats.sum += cond; 9955068a5610SStefano Zampini stats.squaresum += cond2; 9956068a5610SStefano Zampini stats.count++; 99578261a58bSMatthew G. Knepley if (output && cond > limit) { 995843fa8764SMatthew G. Knepley PetscSection coordSection; 995943fa8764SMatthew G. Knepley Vec coordsLocal; 996043fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 996143fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 996243fa8764SMatthew G. Knepley 99639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 99649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 99659566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 996663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 996743fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 996863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 996943fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 99709566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 99719566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 997243fa8764SMatthew G. Knepley } 99739566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 997443fa8764SMatthew G. Knepley } 99759566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 997643fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 997743fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 997843fa8764SMatthew G. Knepley 997943fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 998043fa8764SMatthew G. Knepley PetscReal len; 998143fa8764SMatthew G. Knepley 99829566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 998363a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 998443fa8764SMatthew G. Knepley } 998543fa8764SMatthew G. Knepley } 99869566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 99879566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 998843fa8764SMatthew G. Knepley } 9989068a5610SStefano Zampini } 99909566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9991068a5610SStefano Zampini 9992068a5610SStefano Zampini if (size > 1) { 9993068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9994068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9995068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9996068a5610SStefano Zampini MPI_Op statReduce; 9997068a5610SStefano Zampini 99989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 99999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 100009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 100019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 100029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 100039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 10004068a5610SStefano Zampini } else { 100059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 10006068a5610SStefano Zampini } 10007dd400576SPatrick Sanan if (rank == 0) { 10008068a5610SStefano Zampini count = globalStats.count; 10009068a5610SStefano Zampini min = globalStats.min; 10010068a5610SStefano Zampini max = globalStats.max; 10011068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 10012068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 10013068a5610SStefano Zampini } 10014068a5610SStefano Zampini 1001548a46eb9SPierre 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)); 100169566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 10017068a5610SStefano Zampini 100189566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 10019068a5610SStefano Zampini if (dmCoarse) { 10020068a5610SStefano Zampini PetscBool isplex; 10021068a5610SStefano Zampini 100229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 100231baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 10024068a5610SStefano Zampini } 100253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10026068a5610SStefano Zampini } 10027068a5610SStefano Zampini 10028f108dbd7SJacob Faibussowitsch /*@ 10029f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 10030f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 10031f108dbd7SJacob Faibussowitsch 1003220f4b53cSBarry Smith Collective 10033f108dbd7SJacob Faibussowitsch 10034f108dbd7SJacob Faibussowitsch Input Parameters: 10035a1cb98faSBarry Smith + dm - The `DMPLEX` object 10036a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 10037f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 10038f108dbd7SJacob Faibussowitsch 10039f108dbd7SJacob Faibussowitsch Output Parameters: 1004020f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 10041a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 10042f108dbd7SJacob Faibussowitsch 10043f108dbd7SJacob Faibussowitsch Options Database Keys: 10044a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 10045f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 10046f108dbd7SJacob Faibussowitsch 10047a1cb98faSBarry Smith Level: intermediate 10048a1cb98faSBarry Smith 10049f108dbd7SJacob Faibussowitsch Notes: 10050a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 10051f108dbd7SJacob Faibussowitsch 10052a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 10053f108dbd7SJacob Faibussowitsch 10054f108dbd7SJacob 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 10055f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 10056f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 10057f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 10058f108dbd7SJacob Faibussowitsch 10059f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 10060f108dbd7SJacob Faibussowitsch 10061a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 10062f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 10063f108dbd7SJacob Faibussowitsch 10064f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 10065f108dbd7SJacob Faibussowitsch 100661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 10067f108dbd7SJacob Faibussowitsch @*/ 10068ce78bad3SBarry Smith PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PeOp PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 10069d71ae5a4SJacob Faibussowitsch { 100706ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 100716ed19f2fSJacob Faibussowitsch PetscInt *idx; 100726ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 10073f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 100746ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 10075f108dbd7SJacob Faibussowitsch MPI_Comm comm; 10076f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 10077f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 10078f108dbd7SJacob Faibussowitsch IS glob; 10079f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 10080f108dbd7SJacob Faibussowitsch PetscViewer vwr; 10081f108dbd7SJacob Faibussowitsch 10082f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 10083f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10084ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 100854f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 100866bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 100879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 100889566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 1008963a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 100906ed19f2fSJacob Faibussowitsch { 100916ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 100926ed19f2fSJacob Faibussowitsch 100939566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 10094f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 10095f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 10096f108dbd7SJacob Faibussowitsch 100979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1009898921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 10099f108dbd7SJacob Faibussowitsch } 101006ed19f2fSJacob Faibussowitsch } 10101f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 101024f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 101039566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 101049566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 101059371c9d4SSatish Balay } else { 101069371c9d4SSatish Balay *OrthQualLabel = NULL; 101079371c9d4SSatish Balay } 101089566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 101099566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 10110e2b8d0fcSMatthew G. Knepley PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, &glob)); 101119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 101129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 101139566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 101149566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 101159566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 101169566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 101179566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 101189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 101199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 101209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 101219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 101229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 101239566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 101249566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 101259566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 101266ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 101276ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 10128f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 10129f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 10130898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 10131f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 10132f108dbd7SJacob Faibussowitsch 101336ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 10134f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 10135f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 101369566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 101379566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 10138f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 101399566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 101406ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 101416ed19f2fSJacob Faibussowitsch PetscInt i; 101426ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 10143f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 10144f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 10145f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 10146f108dbd7SJacob Faibussowitsch 10147f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 10148f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 101499566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 10150f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 101516ed19f2fSJacob Faibussowitsch { 101526ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 101536ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 101546ed19f2fSJacob Faibussowitsch 101559566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 101569566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 101579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 101586ed19f2fSJacob Faibussowitsch } 10159f108dbd7SJacob Faibussowitsch 10160f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 10161f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 10162f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 10163f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 10164f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 10165addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 10166addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 10167addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 10168f108dbd7SJacob Faibussowitsch } 10169addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 10170addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 10171addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 10172f108dbd7SJacob Faibussowitsch 10173f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 10174f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 10175f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 10176f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 10177f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 10178f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 10179f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 10180f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 10181f108dbd7SJacob Faibussowitsch } 10182ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 10183ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 10184f108dbd7SJacob Faibussowitsch } 101859566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 101869566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 10187f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 101886ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 10189f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 101909566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 10191f108dbd7SJacob Faibussowitsch } 10192f108dbd7SJacob Faibussowitsch } 101939566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 101949566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 101959566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 101969566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 101979566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 10198648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 10199f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 102009566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 10201f108dbd7SJacob Faibussowitsch } 102029566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 10203648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&vwr)); 102049566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 102053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10206f108dbd7SJacob Faibussowitsch } 10207f108dbd7SJacob Faibussowitsch 10208d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 102091eb70e55SToby Isaac * interpolator construction */ 10210d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 10211d71ae5a4SJacob Faibussowitsch { 102121eb70e55SToby Isaac PetscSection section, newSection, gsection; 102131eb70e55SToby Isaac PetscSF sf; 102141eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 102151eb70e55SToby Isaac 102161eb70e55SToby Isaac PetscFunctionBegin; 102171eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102184f572ea9SToby Isaac PetscAssertPointer(odm, 2); 102199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 102209566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 102215440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 102221eb70e55SToby Isaac if (!ghasConstraints) { 102239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 102241eb70e55SToby Isaac *odm = dm; 102253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102261eb70e55SToby Isaac } 102279566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 10228bb4b53efSMatthew G. Knepley PetscCall(DMCopyFields(dm, PETSC_DETERMINE, PETSC_DETERMINE, *odm)); 102299566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 102309566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 10231eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 102329566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 102339566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 102343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102351eb70e55SToby Isaac } 102361eb70e55SToby Isaac 10237d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 10238d71ae5a4SJacob Faibussowitsch { 102391eb70e55SToby Isaac DM dmco, dmfo; 102401eb70e55SToby Isaac Mat interpo; 102411eb70e55SToby Isaac Vec rscale; 102421eb70e55SToby Isaac Vec cglobalo, clocal; 102431eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 102441eb70e55SToby Isaac PetscBool regular; 102451eb70e55SToby Isaac 102461eb70e55SToby Isaac PetscFunctionBegin; 102479566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 102489566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 102499566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 102509566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 102519566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 102529566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 102539566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 102549566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 102559566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 102569566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 102579566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 102589566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 102599566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 102609566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 102619566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 102629566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 102639566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 102649566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 102659566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 102669566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 102679566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 102689566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 102699566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 102709566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 102711eb70e55SToby Isaac *shift = fglobal; 102729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 102739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 102749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 102759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 102769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 102779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 102789566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 102799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 102803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102811eb70e55SToby Isaac } 102821eb70e55SToby Isaac 10283d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 10284d71ae5a4SJacob Faibussowitsch { 102851eb70e55SToby Isaac PetscObject shifto; 102861eb70e55SToby Isaac Vec shift; 102871eb70e55SToby Isaac 102881eb70e55SToby Isaac PetscFunctionBegin; 102891eb70e55SToby Isaac if (!interp) { 102901eb70e55SToby Isaac Vec rscale; 102911eb70e55SToby Isaac 102929566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 102939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 102941eb70e55SToby Isaac } else { 102959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 102961eb70e55SToby Isaac } 102979566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 102981eb70e55SToby Isaac if (!shifto) { 102999566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 103009566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 103011eb70e55SToby Isaac shifto = (PetscObject)shift; 103029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 103031eb70e55SToby Isaac } 103041eb70e55SToby Isaac shift = (Vec)shifto; 103059566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 103069566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 103079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 103083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103091eb70e55SToby Isaac } 103101eb70e55SToby Isaac 10311bceba477SMatthew G. Knepley /* Pointwise interpolation 10312bceba477SMatthew G. Knepley Just code FEM for now 10313bceba477SMatthew G. Knepley u^f = I u^c 103144ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 103154ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 103164ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 10317bceba477SMatthew G. Knepley */ 10318d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 10319d71ae5a4SJacob Faibussowitsch { 10320bceba477SMatthew G. Knepley PetscSection gsc, gsf; 10321bceba477SMatthew G. Knepley PetscInt m, n; 10322a063dac3SMatthew G. Knepley void *ctx; 1032368132eb9SMatthew G. Knepley DM cdm; 10324cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 10325bceba477SMatthew G. Knepley 10326bceba477SMatthew G. Knepley PetscFunctionBegin; 103279566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 103289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 103299566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 103309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 1033168132eb9SMatthew G. Knepley 103329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 103339566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 103349566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 103359566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 103369566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 1033768132eb9SMatthew G. Knepley 103389566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 103399566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 103409566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 103419566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 103429566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 103434db47ee9SStefano Zampini if (scaling) { 103445d1c2e58SMatthew G. Knepley /* Use naive scaling */ 103459566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 103464db47ee9SStefano Zampini } 103473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10348a063dac3SMatthew G. Knepley } 10349bceba477SMatthew G. Knepley 10350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 10351d71ae5a4SJacob Faibussowitsch { 103526dbf9973SLawrence Mitchell VecScatter ctx; 1035390748bafSMatthew G. Knepley 10354a063dac3SMatthew G. Knepley PetscFunctionBegin; 103559566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 103569566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 103579566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 103583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10359bceba477SMatthew G. Knepley } 10360bceba477SMatthew G. Knepley 10361d71ae5a4SJacob 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[]) 10362d71ae5a4SJacob Faibussowitsch { 10363a102dd69SStefano Zampini const PetscInt f = (PetscInt)PetscRealPart(constants[numConstants]); 10364a102dd69SStefano Zampini const PetscInt Nc = uOff[f + 1] - uOff[f]; 10365a102dd69SStefano Zampini for (PetscInt c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 103663e9753d6SMatthew G. Knepley } 103673e9753d6SMatthew G. Knepley 103681898fd5cSMatthew G. Knepley // The assumption here is that the test field is a vector and the basis field is a scalar (so we need the gradient) 103691898fd5cSMatthew G. Knepley static void g1_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 g1[]) 103701898fd5cSMatthew G. Knepley { 103711898fd5cSMatthew G. Knepley for (PetscInt c = 0; c < dim; ++c) g1[c * dim + c] = 1.0; 103721898fd5cSMatthew G. Knepley } 103731898fd5cSMatthew G. Knepley 103748e9849d2SStefano Zampini PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *lmass, Vec *mass) 10375d71ae5a4SJacob Faibussowitsch { 10376b4937a87SMatthew G. Knepley DM dmc; 10377b4937a87SMatthew G. Knepley PetscDS ds; 10378b4937a87SMatthew G. Knepley Vec ones, locmass; 10379b4937a87SMatthew G. Knepley IS cellIS; 10380b4937a87SMatthew G. Knepley PetscFormKey key; 10381b4937a87SMatthew G. Knepley PetscInt depth; 10382b4937a87SMatthew G. Knepley 10383b4937a87SMatthew G. Knepley PetscFunctionBegin; 103849566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 103859566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 103869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 10387a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 103888e9849d2SStefano Zampini if (mass) PetscCall(DMCreateGlobalVector(dm, mass)); 103898e9849d2SStefano Zampini if (lmass) PetscCall(DMCreateLocalVector(dm, &locmass)); 103908e9849d2SStefano Zampini else PetscCall(DMGetLocalVector(dm, &locmass)); 103918e9849d2SStefano Zampini PetscCall(DMGetLocalVector(dm, &ones)); 103928e9849d2SStefano Zampini PetscCall(DMPlexGetDepth(dm, &depth)); 103938e9849d2SStefano Zampini PetscCall(DMGetStratumIS(dm, "depth", depth, &cellIS)); 103949566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 103959566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10396b4937a87SMatthew G. Knepley key.label = NULL; 10397b4937a87SMatthew G. Knepley key.value = 0; 10398b4937a87SMatthew G. Knepley key.field = 0; 10399b4937a87SMatthew G. Knepley key.part = 0; 10400754e4fbaSMatthew G. Knepley PetscCall(DMPlexComputeJacobianActionByKey(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 104019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 104028e9849d2SStefano Zampini if (mass) { 104038e9849d2SStefano Zampini PetscCall(DMLocalToGlobalBegin(dm, locmass, ADD_VALUES, *mass)); 104048e9849d2SStefano Zampini PetscCall(DMLocalToGlobalEnd(dm, locmass, ADD_VALUES, *mass)); 104058e9849d2SStefano Zampini } 104068e9849d2SStefano Zampini PetscCall(DMRestoreLocalVector(dm, &ones)); 104078e9849d2SStefano Zampini if (lmass) *lmass = locmass; 104088e9849d2SStefano Zampini else PetscCall(DMRestoreLocalVector(dm, &locmass)); 104099566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 104103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10411b4937a87SMatthew G. Knepley } 10412b4937a87SMatthew G. Knepley 10413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10414d71ae5a4SJacob Faibussowitsch { 10415bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10416bd041c0cSMatthew G. Knepley PetscInt m, n; 10417bd041c0cSMatthew G. Knepley void *ctx; 10418bd041c0cSMatthew G. Knepley DM cdm; 10419bd041c0cSMatthew G. Knepley PetscBool regular; 10420bd041c0cSMatthew G. Knepley 10421bd041c0cSMatthew G. Knepley PetscFunctionBegin; 104223e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 104233e9753d6SMatthew G. Knepley DM dmc; 104243e9753d6SMatthew G. Knepley PetscDS ds; 10425b4937a87SMatthew G. Knepley PetscWeakForm wf; 104263e9753d6SMatthew G. Knepley Vec u; 104273e9753d6SMatthew G. Knepley IS cellIS; 1042806ad1575SMatthew G. Knepley PetscFormKey key; 104293e9753d6SMatthew G. Knepley PetscInt depth; 104303e9753d6SMatthew G. Knepley 104319566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 104329566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 104339566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 104349566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 104359566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 10436a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 104379566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 104388d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 104399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 104409566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 104419566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 104426528b96dSMatthew G. Knepley key.label = NULL; 104436528b96dSMatthew G. Knepley key.value = 0; 104446528b96dSMatthew G. Knepley key.field = 0; 1044506ad1575SMatthew G. Knepley key.part = 0; 10446754e4fbaSMatthew G. Knepley PetscCall(DMPlexComputeJacobianByKey(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 104479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 104488d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 104499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 104503e9753d6SMatthew G. Knepley } else { 104519566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 104529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 104539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 104549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10455bd041c0cSMatthew G. Knepley 104569566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 104579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 104589566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 104599566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10460bd041c0cSMatthew G. Knepley 104619566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 104629566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 104639566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 104649566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 104653e9753d6SMatthew G. Knepley } 104669566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 104673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10468bd041c0cSMatthew G. Knepley } 10469bd041c0cSMatthew G. Knepley 104701898fd5cSMatthew G. Knepley PetscErrorCode DMCreateGradientMatrix_Plex(DM dmc, DM dmr, Mat *derv) 104711898fd5cSMatthew G. Knepley { 104721898fd5cSMatthew G. Knepley PetscSection gsc, gsf; 104731898fd5cSMatthew G. Knepley PetscInt m, n; 104741898fd5cSMatthew G. Knepley void *ctx; 104751898fd5cSMatthew G. Knepley 104761898fd5cSMatthew G. Knepley PetscFunctionBegin; 104771898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dmr, &gsf)); 104781898fd5cSMatthew G. Knepley PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 104791898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dmc, &gsc)); 104801898fd5cSMatthew G. Knepley PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 104811898fd5cSMatthew G. Knepley 104821898fd5cSMatthew G. Knepley PetscCall(MatCreate(PetscObjectComm((PetscObject)dmc), derv)); 104831898fd5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*derv, "Plex Derivative Matrix")); 104841898fd5cSMatthew G. Knepley PetscCall(MatSetSizes(*derv, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 104851898fd5cSMatthew G. Knepley PetscCall(MatSetType(*derv, dmc->mattype)); 104861898fd5cSMatthew G. Knepley 104871898fd5cSMatthew G. Knepley PetscCall(DMGetApplicationContext(dmr, &ctx)); 104881898fd5cSMatthew G. Knepley { 104891898fd5cSMatthew G. Knepley DM ndmr; 104901898fd5cSMatthew G. Knepley PetscDS ds; 104911898fd5cSMatthew G. Knepley PetscWeakForm wf; 104921898fd5cSMatthew G. Knepley Vec u; 104931898fd5cSMatthew G. Knepley IS cellIS; 104941898fd5cSMatthew G. Knepley PetscFormKey key; 104951898fd5cSMatthew G. Knepley PetscInt depth, Nf; 104961898fd5cSMatthew G. Knepley 104971898fd5cSMatthew G. Knepley PetscCall(DMClone(dmr, &ndmr)); 104981898fd5cSMatthew G. Knepley PetscCall(DMCopyDisc(dmr, ndmr)); 104991898fd5cSMatthew G. Knepley PetscCall(DMGetDS(ndmr, &ds)); 105001898fd5cSMatthew G. Knepley PetscCall(PetscDSGetWeakForm(ds, &wf)); 105011898fd5cSMatthew G. Knepley PetscCall(PetscWeakFormClear(wf)); 105021898fd5cSMatthew G. Knepley PetscCall(PetscDSGetNumFields(ds, &Nf)); 105031898fd5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, NULL, g1_identity_private, NULL, NULL)); 105041898fd5cSMatthew G. Knepley PetscCall(DMGetLocalVector(ndmr, &u)); 105051898fd5cSMatthew G. Knepley PetscCall(DMPlexGetDepth(ndmr, &depth)); 105061898fd5cSMatthew G. Knepley PetscCall(DMGetStratumIS(ndmr, "depth", depth, &cellIS)); 105071898fd5cSMatthew G. Knepley PetscCall(MatZeroEntries(*derv)); 105081898fd5cSMatthew G. Knepley key.label = NULL; 105091898fd5cSMatthew G. Knepley key.value = 0; 105101898fd5cSMatthew G. Knepley key.field = 0; 105111898fd5cSMatthew G. Knepley key.part = 0; 105121898fd5cSMatthew G. Knepley PetscCall(DMPlexComputeJacobianByKeyGeneral(ndmr, dmc, key, cellIS, 0.0, 0.0, u, NULL, *derv, *derv, NULL)); 105131898fd5cSMatthew G. Knepley PetscCall(ISDestroy(&cellIS)); 105141898fd5cSMatthew G. Knepley PetscCall(DMRestoreLocalVector(ndmr, &u)); 105151898fd5cSMatthew G. Knepley PetscCall(DMDestroy(&ndmr)); 105161898fd5cSMatthew G. Knepley } 105171898fd5cSMatthew G. Knepley PetscCall(MatViewFromOptions(*derv, NULL, "-gradient_mat_view")); 105181898fd5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 105191898fd5cSMatthew G. Knepley } 105201898fd5cSMatthew G. Knepley 105210aef6b92SMatthew G. Knepley /*@ 105220aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 105230aef6b92SMatthew G. Knepley 105240aef6b92SMatthew G. Knepley Input Parameter: 10525a1cb98faSBarry Smith . dm - The `DMPLEX` object 105260aef6b92SMatthew G. Knepley 105270aef6b92SMatthew G. Knepley Output Parameter: 105280aef6b92SMatthew G. Knepley . regular - The flag 105290aef6b92SMatthew G. Knepley 105300aef6b92SMatthew G. Knepley Level: intermediate 105310aef6b92SMatthew G. Knepley 105321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 105330aef6b92SMatthew G. Knepley @*/ 10534d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10535d71ae5a4SJacob Faibussowitsch { 105360aef6b92SMatthew G. Knepley PetscFunctionBegin; 105370aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105384f572ea9SToby Isaac PetscAssertPointer(regular, 2); 105390aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 105403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105410aef6b92SMatthew G. Knepley } 105420aef6b92SMatthew G. Knepley 105430aef6b92SMatthew G. Knepley /*@ 105440aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 105450aef6b92SMatthew G. Knepley 105460aef6b92SMatthew G. Knepley Input Parameters: 10547a1cb98faSBarry Smith + dm - The `DMPLEX` object 105480aef6b92SMatthew G. Knepley - regular - The flag 105490aef6b92SMatthew G. Knepley 105500aef6b92SMatthew G. Knepley Level: intermediate 105510aef6b92SMatthew G. Knepley 105521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 105530aef6b92SMatthew G. Knepley @*/ 10554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10555d71ae5a4SJacob Faibussowitsch { 105560aef6b92SMatthew G. Knepley PetscFunctionBegin; 105570aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105580aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 105593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105600aef6b92SMatthew G. Knepley } 105610aef6b92SMatthew G. Knepley 10562a68b90caSToby Isaac /*@ 10563f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10564a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10565a68b90caSToby Isaac 10566a1cb98faSBarry Smith Not Collective 10567a68b90caSToby Isaac 10568f899ff85SJose E. Roman Input Parameter: 10569a1cb98faSBarry Smith . dm - The `DMPLEX` object 10570a68b90caSToby Isaac 10571a68b90caSToby Isaac Output Parameters: 1057220f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1057320f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10574a68b90caSToby Isaac 10575a68b90caSToby Isaac Level: intermediate 10576a68b90caSToby Isaac 105771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10578a68b90caSToby Isaac @*/ 10579ce78bad3SBarry Smith PetscErrorCode DMPlexGetAnchors(DM dm, PeOp PetscSection *anchorSection, PeOp IS *anchorIS) 10580d71ae5a4SJacob Faibussowitsch { 10581a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10582a68b90caSToby Isaac 10583a68b90caSToby Isaac PetscFunctionBegin; 10584a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105859566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10586a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10587a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 105883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10589a68b90caSToby Isaac } 10590a68b90caSToby Isaac 10591a68b90caSToby Isaac /*@ 10592a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10593a68b90caSToby Isaac 1059420f4b53cSBarry Smith Collective 10595a68b90caSToby Isaac 10596a68b90caSToby Isaac Input Parameters: 10597a1cb98faSBarry Smith + dm - The `DMPLEX` object 10598a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10599a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10600a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10601a68b90caSToby Isaac 10602a68b90caSToby Isaac Level: intermediate 10603a68b90caSToby Isaac 10604a1cb98faSBarry Smith Notes: 10605a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10606a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10607a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10608a4e35b19SJacob Faibussowitsch 10609a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10610a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10611a1cb98faSBarry Smith 1061220f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10613a1cb98faSBarry Smith 106141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10615a68b90caSToby Isaac @*/ 10616d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10617d71ae5a4SJacob Faibussowitsch { 10618a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10619e228b242SToby Isaac PetscMPIInt result; 10620a68b90caSToby Isaac 10621a68b90caSToby Isaac PetscFunctionBegin; 10622a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10623e228b242SToby Isaac if (anchorSection) { 10624e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 106259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 106261dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10627e228b242SToby Isaac } 10628e228b242SToby Isaac if (anchorIS) { 10629e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 106309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 106311dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10632e228b242SToby Isaac } 10633a68b90caSToby Isaac 106349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 106359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10636a68b90caSToby Isaac plex->anchorSection = anchorSection; 10637a68b90caSToby Isaac 106389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 106399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10640a68b90caSToby Isaac plex->anchorIS = anchorIS; 10641a68b90caSToby Isaac 10642cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10643a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10644a68b90caSToby Isaac const PetscInt *anchors; 10645a68b90caSToby Isaac 106469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 106479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 106489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10649a68b90caSToby Isaac for (a = 0; a < size; a++) { 10650a68b90caSToby Isaac PetscInt p; 10651a68b90caSToby Isaac 10652a68b90caSToby Isaac p = anchors[a]; 10653a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10654a68b90caSToby Isaac PetscInt dof; 10655a68b90caSToby Isaac 106569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10657a68b90caSToby Isaac if (dof) { 106589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1065963a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10660a68b90caSToby Isaac } 10661a68b90caSToby Isaac } 10662a68b90caSToby Isaac } 106639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10664a68b90caSToby Isaac } 10665f7c74593SToby Isaac /* reset the generic constraints */ 106669566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 106673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10668a68b90caSToby Isaac } 10669a68b90caSToby Isaac 10670d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10671d71ae5a4SJacob Faibussowitsch { 10672f7c74593SToby Isaac PetscSection anchorSection; 106736995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10674a68b90caSToby Isaac 10675a68b90caSToby Isaac PetscFunctionBegin; 10676a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 106779566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 106789566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 106799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 106806995de1eSToby Isaac if (numFields) { 10681719ab38cSToby Isaac PetscInt f; 106829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10683719ab38cSToby Isaac 10684719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10685719ab38cSToby Isaac PetscInt numComp; 10686719ab38cSToby Isaac 106879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 106889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10689719ab38cSToby Isaac } 106906995de1eSToby Isaac } 106919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 106929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 106936995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 106946995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 106956995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 106969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10697a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 106989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10699a68b90caSToby Isaac if (dof) { 107009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 107019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10702a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 107039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 107049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10705a68b90caSToby Isaac } 10706a68b90caSToby Isaac } 10707a68b90caSToby Isaac } 107089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 107099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 107103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10711a68b90caSToby Isaac } 10712a68b90caSToby Isaac 10713d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10714d71ae5a4SJacob Faibussowitsch { 10715f7c74593SToby Isaac PetscSection aSec; 10716ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 107170ac89760SToby Isaac const PetscInt *anchors; 107180ac89760SToby Isaac PetscInt numFields, f; 1071966ad2231SToby Isaac IS aIS; 10720e19f7ee6SMark Adams MatType mtype; 10721e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 107220ac89760SToby Isaac 107230ac89760SToby Isaac PetscFunctionBegin; 107240ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 107259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 107269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 107279566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 107289566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 107299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 107309566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 107319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 107329566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10733e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10734e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10735e19f7ee6SMark Adams else mtype = MATSEQAIJ; 107369566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 107379566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 107389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 107396995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 107409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 107419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 107429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 107430ac89760SToby Isaac i[0] = 0; 107449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 107450ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10746f19733c5SToby Isaac PetscInt rDof, rOff, r; 10747f19733c5SToby Isaac 107489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10749f19733c5SToby Isaac if (!rDof) continue; 107509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 107510ac89760SToby Isaac if (numFields) { 107520ac89760SToby Isaac for (f = 0; f < numFields; f++) { 107530ac89760SToby Isaac annz = 0; 10754f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10755f19733c5SToby Isaac a = anchors[rOff + r]; 10756ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 107580ac89760SToby Isaac annz += aDof; 107590ac89760SToby Isaac } 107609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 107619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10762ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 107630ac89760SToby Isaac } 107642f7452b8SBarry Smith } else { 107650ac89760SToby Isaac annz = 0; 107669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 107670ac89760SToby Isaac for (q = 0; q < dof; q++) { 10768ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10769ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 107710ac89760SToby Isaac annz += aDof; 107720ac89760SToby Isaac } 107739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 107749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10775ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 107760ac89760SToby Isaac } 107770ac89760SToby Isaac } 107780ac89760SToby Isaac nnz = i[m]; 107799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 107800ac89760SToby Isaac offset = 0; 107810ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 107820ac89760SToby Isaac if (numFields) { 107830ac89760SToby Isaac for (f = 0; f < numFields; f++) { 107849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 107850ac89760SToby Isaac for (q = 0; q < dof; q++) { 107860ac89760SToby Isaac PetscInt rDof, rOff, r; 107879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 107889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 107890ac89760SToby Isaac for (r = 0; r < rDof; r++) { 107900ac89760SToby Isaac PetscInt s; 107910ac89760SToby Isaac 107920ac89760SToby Isaac a = anchors[rOff + r]; 10793ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 107959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10796ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 107970ac89760SToby Isaac } 107980ac89760SToby Isaac } 107990ac89760SToby Isaac } 108002f7452b8SBarry Smith } else { 108019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 108020ac89760SToby Isaac for (q = 0; q < dof; q++) { 108030ac89760SToby Isaac PetscInt rDof, rOff, r; 108049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 108059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 108060ac89760SToby Isaac for (r = 0; r < rDof; r++) { 108070ac89760SToby Isaac PetscInt s; 108080ac89760SToby Isaac 108090ac89760SToby Isaac a = anchors[rOff + r]; 10810ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 108119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 108129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10813ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 108140ac89760SToby Isaac } 108150ac89760SToby Isaac } 108160ac89760SToby Isaac } 108170ac89760SToby Isaac } 108189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 108199566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 108209566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 108219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 108223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108230ac89760SToby Isaac } 108240ac89760SToby Isaac 10825d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10826d71ae5a4SJacob Faibussowitsch { 10827f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10828f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1082966ad2231SToby Isaac Mat cMat; 1083066ad2231SToby Isaac 1083166ad2231SToby Isaac PetscFunctionBegin; 1083266ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 108339566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1083466ad2231SToby Isaac if (anchorSection) { 1083544a7f3ddSMatthew G. Knepley PetscInt Nf; 10836e228b242SToby Isaac 108379566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 108389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 108399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 108409566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 108419566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 108429566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 108439566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 108449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1084566ad2231SToby Isaac } 108463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1084766ad2231SToby Isaac } 10848a93c429eSMatthew G. Knepley 10849d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10850d71ae5a4SJacob Faibussowitsch { 10851a93c429eSMatthew G. Knepley IS subis; 10852a93c429eSMatthew G. Knepley PetscSection section, subsection; 10853a93c429eSMatthew G. Knepley 10854a93c429eSMatthew G. Knepley PetscFunctionBegin; 108559566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1085628b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1085728b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10858a93c429eSMatthew G. Knepley /* Create subdomain */ 1085971f1c950SStefano Zampini PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, PetscObjectComm((PetscObject)dm), NULL, subdm)); 10860a93c429eSMatthew G. Knepley /* Create submodel */ 108619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 108629566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 108639566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 108649566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 108659566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10866a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10867a93c429eSMatthew G. Knepley if (is) { 10868a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10869a93c429eSMatthew G. Knepley IS spIS; 10870a93c429eSMatthew G. Knepley const PetscInt *spmap; 10871a93c429eSMatthew G. Knepley PetscInt *subIndices; 10872a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10873a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10874a93c429eSMatthew G. Knepley 108759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 108769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 108779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 108789566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 108799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 108809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10881a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10882a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10883a93c429eSMatthew G. Knepley 108849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10885a93c429eSMatthew G. Knepley if (gdof > 0) { 10886a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10887a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10888a93c429eSMatthew G. Knepley 108899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 108909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10891a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10892a93c429eSMatthew G. Knepley } 10893a93c429eSMatthew G. Knepley subSize += pSubSize; 10894a93c429eSMatthew G. Knepley if (pSubSize) { 10895a93c429eSMatthew G. Knepley if (bs < 0) { 10896a93c429eSMatthew G. Knepley bs = pSubSize; 10897a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10898a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10899a93c429eSMatthew G. Knepley bs = 1; 10900a93c429eSMatthew G. Knepley } 10901a93c429eSMatthew G. Knepley } 10902a93c429eSMatthew G. Knepley } 10903a93c429eSMatthew G. Knepley } 10904a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 109051690c2aeSBarry Smith bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs; 109069371c9d4SSatish Balay bsLocal[1] = bs; 109079566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 109089371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 109099371c9d4SSatish Balay bs = 1; 109109371c9d4SSatish Balay } else { 109119371c9d4SSatish Balay bs = bsMinMax[0]; 109129371c9d4SSatish Balay } 109139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10914a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10915a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10916a93c429eSMatthew G. Knepley 109179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10918a93c429eSMatthew G. Knepley if (gdof > 0) { 10919a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10920a93c429eSMatthew G. Knepley 109219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10922a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10923a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10924a93c429eSMatthew G. Knepley 10925a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10926a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 109279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 109289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10929a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10930a93c429eSMatthew G. Knepley } 109319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 109329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10933ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10934a93c429eSMatthew G. Knepley } 10935a93c429eSMatthew G. Knepley } 10936a93c429eSMatthew G. Knepley } 109379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 109389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10939a93c429eSMatthew G. Knepley if (bs > 1) { 10940a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10941a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10942a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10943a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 109449371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 109459371c9d4SSatish Balay set = 0; 109469371c9d4SSatish Balay break; 109479371c9d4SSatish Balay } 10948a93c429eSMatthew G. Knepley } 10949a93c429eSMatthew G. Knepley } 109509566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10951a93c429eSMatthew G. Knepley } 109524758e3ceSMatthew G. Knepley // Attach nullspace 109534758e3ceSMatthew G. Knepley if (dm->nullspaceConstructors) { 10954a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10955a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10956a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10957a93c429eSMatthew G. Knepley } 10958a93c429eSMatthew G. Knepley if (f < Nf) { 10959a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 109609566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 109616823f3c5SBlaise Bourdin 109629566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 109639566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10964a93c429eSMatthew G. Knepley } 10965a93c429eSMatthew G. Knepley } 109664758e3ceSMatthew G. Knepley } 109673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10968a93c429eSMatthew G. Knepley } 10969c0f0dcc3SMatthew G. Knepley 10970c0f0dcc3SMatthew G. Knepley /*@ 10971c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10972c0f0dcc3SMatthew G. Knepley 10973a1cb98faSBarry Smith Input Parameters: 10974a1cb98faSBarry Smith + dm - The `DM` 109752a8381b2SBarry Smith - unused - unused argument 10976a1cb98faSBarry Smith 10977a1cb98faSBarry Smith Options Database Key: 10978a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10979c0f0dcc3SMatthew G. Knepley 10980c0f0dcc3SMatthew G. Knepley Level: developer 10981c0f0dcc3SMatthew G. Knepley 109821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10983c0f0dcc3SMatthew G. Knepley @*/ 109842a8381b2SBarry Smith PetscErrorCode DMPlexMonitorThroughput(DM dm, void *unused) 10985d71ae5a4SJacob Faibussowitsch { 10986b665b14eSToby Isaac PetscLogHandler default_handler; 10987b665b14eSToby Isaac 109882611ad71SToby Isaac PetscFunctionBegin; 109892611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10990b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10991b665b14eSToby Isaac if (default_handler) { 10992c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10993c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10994835f2295SStefano Zampini PetscLogDouble cellRate, flopRate; 10995c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10996c0f0dcc3SMatthew G. Knepley const char *name; 10997c0f0dcc3SMatthew G. Knepley 109989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 109999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 110009566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 110019566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 11002b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 11003c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 11004c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 11005c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 11006835f2295SStefano Zampini 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, cellRate, flopRate / 1.e6)); 110072611ad71SToby Isaac } else { 11008b665b14eSToby 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."); 110092611ad71SToby Isaac } 110103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11011c0f0dcc3SMatthew G. Knepley } 11012