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> 20436823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 20441e50132fSMatthew G. Knepley #endif 20451e50132fSMatthew G. Knepley 2046d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 2047d71ae5a4SJacob Faibussowitsch { 20489f196a02SMartin Diehl PetscBool isascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns, ispython; 2049002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 2050552f7358SJed Brown 2051552f7358SJed Brown PetscFunctionBegin; 2052552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2053552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20549f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 20559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 20569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 20589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 20599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 20605f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 206122d6dc08SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 20629f196a02SMartin Diehl if (isascii) { 20638135c375SStefano Zampini PetscViewerFormat format; 20649566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20651baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 20661baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 2067c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 2068c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 20699566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 2070c6ccd67eSMatthew G. Knepley #else 2071c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2072552f7358SJed Brown #endif 2073e412dcbdSMatthew G. Knepley } else if (isvtk) { 20749566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 2075e412dcbdSMatthew G. Knepley } else if (isdraw) { 2076e44f6aebSMatthew G. Knepley DM hdm; 2077e44f6aebSMatthew G. Knepley 2078e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 2079e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 2080e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 20818135c375SStefano Zampini } else if (isglvis) { 20829566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 20831e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 20841e50132fSMatthew G. Knepley } else if (isexodus) { 20856823f3c5SBlaise Bourdin /* 2086caff39ffSPierre Jolivet ExodusII requires that all sets be part of exactly one cell set. 20876823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 2088da81f932SPierre Jolivet with ID 1, containing all cells. 20896823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 20906823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 20916823f3c5SBlaise Bourdin */ 20926823f3c5SBlaise Bourdin PetscInt numCS; 20939566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 20946823f3c5SBlaise Bourdin if (!numCS) { 20951e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 20969566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 20979566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 20989566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 20996823f3c5SBlaise Bourdin } 21009566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 21011e50132fSMatthew G. Knepley #endif 21025f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 21035f34f2dcSJed Brown } else if (iscgns) { 21045f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 21055f34f2dcSJed Brown #endif 210622d6dc08SStefano Zampini } else if (ispython) { 210722d6dc08SStefano Zampini PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm)); 21081baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 2109cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 21109566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 2111cb3ba0daSMatthew G. Knepley if (flg) { 2112cb3ba0daSMatthew G. Knepley Vec ranks; 21139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 21149566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 21159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 2116cb3ba0daSMatthew G. Knepley } 2117002a2709SMatthew G. Knepley /* Optionally view a label */ 21189566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 2119002a2709SMatthew G. Knepley if (flg) { 2120002a2709SMatthew G. Knepley DMLabel label; 2121002a2709SMatthew G. Knepley Vec val; 2122002a2709SMatthew G. Knepley 21239566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 212428b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 21259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 21269566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 21279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 2128002a2709SMatthew G. Knepley } 21293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2130552f7358SJed Brown } 2131552f7358SJed Brown 21327f96f51bSksagiyam /*@ 2133a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 21347f96f51bSksagiyam 213520f4b53cSBarry Smith Collective 21367f96f51bSksagiyam 21377f96f51bSksagiyam Input Parameters: 2138a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2139a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 21407f96f51bSksagiyam 21417f96f51bSksagiyam Level: advanced 21427f96f51bSksagiyam 21431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 21447f96f51bSksagiyam @*/ 2145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2146d71ae5a4SJacob Faibussowitsch { 21477f96f51bSksagiyam PetscBool ishdf5; 21487f96f51bSksagiyam 21497f96f51bSksagiyam PetscFunctionBegin; 21507f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21517f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21539566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 21547f96f51bSksagiyam if (ishdf5) { 21557f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 21567f96f51bSksagiyam IS globalPointNumbering; 2157966bd95aSPierre Jolivet PetscViewerFormat format; 21587f96f51bSksagiyam 2159966bd95aSPierre Jolivet PetscCall(PetscViewerGetFormat(viewer, &format)); 2160966bd95aSPierre 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]); 21619566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21629566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 21647f96f51bSksagiyam #else 21657f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 21667f96f51bSksagiyam #endif 21677f96f51bSksagiyam } 21689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 21693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21707f96f51bSksagiyam } 21717f96f51bSksagiyam 217277b8e257Sksagiyam /*@ 2173a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 217477b8e257Sksagiyam 217520f4b53cSBarry Smith Collective 217677b8e257Sksagiyam 217777b8e257Sksagiyam Input Parameters: 2178a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2179a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 218077b8e257Sksagiyam 218177b8e257Sksagiyam Level: advanced 218277b8e257Sksagiyam 21831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 218477b8e257Sksagiyam @*/ 2185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2186d71ae5a4SJacob Faibussowitsch { 218777b8e257Sksagiyam PetscBool ishdf5; 218877b8e257Sksagiyam 218977b8e257Sksagiyam PetscFunctionBegin; 219077b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 219177b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 219477b8e257Sksagiyam if (ishdf5) { 219577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 219677b8e257Sksagiyam PetscViewerFormat format; 2197966bd95aSPierre Jolivet 21989566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2199966bd95aSPierre 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]); 22009566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 220177b8e257Sksagiyam #else 220277b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 220377b8e257Sksagiyam #endif 220477b8e257Sksagiyam } 22059566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 22063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 220777b8e257Sksagiyam } 220877b8e257Sksagiyam 2209bd6565f1Sksagiyam /*@ 2210a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2211bd6565f1Sksagiyam 221220f4b53cSBarry Smith Collective 2213bd6565f1Sksagiyam 2214bd6565f1Sksagiyam Input Parameters: 2215a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2216a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2217bd6565f1Sksagiyam 2218bd6565f1Sksagiyam Level: advanced 2219bd6565f1Sksagiyam 22201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2221bd6565f1Sksagiyam @*/ 2222d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2223d71ae5a4SJacob Faibussowitsch { 2224bd6565f1Sksagiyam PetscBool ishdf5; 2225bd6565f1Sksagiyam 2226bd6565f1Sksagiyam PetscFunctionBegin; 2227bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2228bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22309566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2231bd6565f1Sksagiyam if (ishdf5) { 2232bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2233bd6565f1Sksagiyam IS globalPointNumbering; 2234bd6565f1Sksagiyam PetscViewerFormat format; 2235bd6565f1Sksagiyam 22369566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2237966bd95aSPierre 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]); 22389566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 22399566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 22409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 2241bd6565f1Sksagiyam #else 2242bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2243bd6565f1Sksagiyam #endif 2244bd6565f1Sksagiyam } 22459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 22463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2247bd6565f1Sksagiyam } 2248bd6565f1Sksagiyam 2249021affd3Sksagiyam /*@ 2250a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2251021affd3Sksagiyam 225220f4b53cSBarry Smith Collective 2253021affd3Sksagiyam 2254021affd3Sksagiyam Input Parameters: 2255a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2256a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 22570318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2258021affd3Sksagiyam 2259021affd3Sksagiyam Level: advanced 2260021affd3Sksagiyam 2261021affd3Sksagiyam Notes: 2262420bcc1bSBarry 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. 2263021affd3Sksagiyam 22640318f8a0SStefano 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. 2265021affd3Sksagiyam 22661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2267021affd3Sksagiyam @*/ 2268d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2269d71ae5a4SJacob Faibussowitsch { 2270021affd3Sksagiyam PetscBool ishdf5; 2271021affd3Sksagiyam 2272021affd3Sksagiyam PetscFunctionBegin; 2273021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2274021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22750318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2276021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22789566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2279021affd3Sksagiyam if (ishdf5) { 2280021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 22819566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2282021affd3Sksagiyam #else 2283021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2284021affd3Sksagiyam #endif 2285021affd3Sksagiyam } 22869566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 22873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2288021affd3Sksagiyam } 2289021affd3Sksagiyam 22903e97647fSksagiyam /*@ 22913e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 22923e97647fSksagiyam 229320f4b53cSBarry Smith Collective 22943e97647fSksagiyam 22953e97647fSksagiyam Input Parameters: 2296a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2297a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22980318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 22993e97647fSksagiyam - vec - The global vector to be saved 23003e97647fSksagiyam 23013e97647fSksagiyam Level: advanced 23023e97647fSksagiyam 23033e97647fSksagiyam Notes: 23040318f8a0SStefano 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. 23053e97647fSksagiyam 230660225df5SJacob Faibussowitsch Calling sequence: 2307a1cb98faSBarry Smith .vb 2308a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2309a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2310a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2311a1cb98faSBarry Smith DMClone(dm, §iondm); 2312a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2313a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2314a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2315a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2316a1cb98faSBarry Smith PetscSectionSetUp(section); 2317a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2318a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2319a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2320a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2321a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2322a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2323a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2324a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2325a1cb98faSBarry Smith DMDestroy(§iondm); 2326a1cb98faSBarry Smith DMDestroy(&dm); 2327a1cb98faSBarry Smith .ve 23283e97647fSksagiyam 23291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 23303e97647fSksagiyam @*/ 2331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2332d71ae5a4SJacob Faibussowitsch { 23333e97647fSksagiyam PetscBool ishdf5; 23343e97647fSksagiyam 23353e97647fSksagiyam PetscFunctionBegin; 23363e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23373e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23380318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 23393e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23403e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 23413e97647fSksagiyam /* Check consistency */ 23423e97647fSksagiyam { 23433e97647fSksagiyam PetscSection section; 23443e97647fSksagiyam PetscBool includesConstraints; 23453e97647fSksagiyam PetscInt m, m1; 23463e97647fSksagiyam 23479566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23489566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 23499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23509566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23519566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 235263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 23533e97647fSksagiyam } 23549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23559566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 23563e97647fSksagiyam if (ishdf5) { 23573e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23589566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23593e97647fSksagiyam #else 23603e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23613e97647fSksagiyam #endif 23623e97647fSksagiyam } 23639566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 23643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23653e97647fSksagiyam } 23663e97647fSksagiyam 23673e97647fSksagiyam /*@ 23683e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 23693e97647fSksagiyam 237020f4b53cSBarry Smith Collective 23713e97647fSksagiyam 23723e97647fSksagiyam Input Parameters: 2373a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2374a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 23750318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 23763e97647fSksagiyam - vec - The local vector to be saved 23773e97647fSksagiyam 23783e97647fSksagiyam Level: advanced 23793e97647fSksagiyam 2380a1cb98faSBarry Smith Note: 23810318f8a0SStefano 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. 23823e97647fSksagiyam 238360225df5SJacob Faibussowitsch Calling sequence: 2384a1cb98faSBarry Smith .vb 2385a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2386a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2387a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2388a1cb98faSBarry Smith DMClone(dm, §iondm); 2389a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2390a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2391a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2392a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2393a1cb98faSBarry Smith PetscSectionSetUp(section); 2394a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2395a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2396a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2397a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2398a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2399a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2400a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2401a1cb98faSBarry Smith DMDestroy(§iondm); 2402a1cb98faSBarry Smith DMDestroy(&dm); 2403a1cb98faSBarry Smith .ve 24043e97647fSksagiyam 24051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 24063e97647fSksagiyam @*/ 2407d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2408d71ae5a4SJacob Faibussowitsch { 24093e97647fSksagiyam PetscBool ishdf5; 24103e97647fSksagiyam 24113e97647fSksagiyam PetscFunctionBegin; 24123e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24133e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24140318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 24153e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 24163e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 24173e97647fSksagiyam /* Check consistency */ 24183e97647fSksagiyam { 24193e97647fSksagiyam PetscSection section; 24203e97647fSksagiyam PetscBool includesConstraints; 24213e97647fSksagiyam PetscInt m, m1; 24223e97647fSksagiyam 24239566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 24249566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 24259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 24269566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 24279566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 242863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 24293e97647fSksagiyam } 24309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 24323e97647fSksagiyam if (ishdf5) { 24333e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 24349566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 24353e97647fSksagiyam #else 24363e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24373e97647fSksagiyam #endif 24383e97647fSksagiyam } 24399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 24403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24413e97647fSksagiyam } 24423e97647fSksagiyam 2443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2444d71ae5a4SJacob Faibussowitsch { 2445d4f5a9a0SVaclav Hapla PetscBool ishdf5; 24462c40f234SMatthew G. Knepley 24472c40f234SMatthew G. Knepley PetscFunctionBegin; 24482c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24492c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2451d4f5a9a0SVaclav Hapla if (ishdf5) { 24522c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 24539c48423bSVaclav Hapla PetscViewerFormat format; 24549566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24559c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 24569566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2457509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24589566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 245998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24612c40f234SMatthew G. Knepley #else 24622c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2463552f7358SJed Brown #endif 246498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2465552f7358SJed Brown } 2466552f7358SJed Brown 2467ea8e1828Sksagiyam /*@ 2468a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2469ea8e1828Sksagiyam 247020f4b53cSBarry Smith Collective 2471ea8e1828Sksagiyam 2472ea8e1828Sksagiyam Input Parameters: 2473a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2474a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2475ea8e1828Sksagiyam 24762fe279fdSBarry Smith Output Parameter: 24772c9a7b26SBarry 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; 24782c9a7b26SBarry Smith `NULL` if unneeded 2479dec9e869Sksagiyam 2480ea8e1828Sksagiyam Level: advanced 2481ea8e1828Sksagiyam 24821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2483a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2484ea8e1828Sksagiyam @*/ 2485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2486d71ae5a4SJacob Faibussowitsch { 2487ea8e1828Sksagiyam PetscBool ishdf5; 2488ea8e1828Sksagiyam 2489ea8e1828Sksagiyam PetscFunctionBegin; 2490ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2491ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24924f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 24939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2495ea8e1828Sksagiyam if (ishdf5) { 2496ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2497ea8e1828Sksagiyam PetscViewerFormat format; 2498966bd95aSPierre Jolivet 24999566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2500966bd95aSPierre 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]); 25019566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 2502ea8e1828Sksagiyam #else 2503ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2504ea8e1828Sksagiyam #endif 2505ea8e1828Sksagiyam } 25069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 25073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2508ea8e1828Sksagiyam } 2509ea8e1828Sksagiyam 25103e701f1cSksagiyam /*@ 2511a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 25123e701f1cSksagiyam 251320f4b53cSBarry Smith Collective 25143e701f1cSksagiyam 25153e701f1cSksagiyam Input Parameters: 2516a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2517a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2518a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 25193e701f1cSksagiyam 25203e701f1cSksagiyam Level: advanced 25213e701f1cSksagiyam 25221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2523a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25243e701f1cSksagiyam @*/ 2525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2526d71ae5a4SJacob Faibussowitsch { 25273e701f1cSksagiyam PetscBool ishdf5; 25283e701f1cSksagiyam 25293e701f1cSksagiyam PetscFunctionBegin; 25303e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25313e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2532c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 25339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 25353e701f1cSksagiyam if (ishdf5) { 25363e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 25373e701f1cSksagiyam PetscViewerFormat format; 2538966bd95aSPierre Jolivet 25399566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2540966bd95aSPierre 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]); 25419566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 25423e701f1cSksagiyam #else 25433e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25443e701f1cSksagiyam #endif 25453e701f1cSksagiyam } 25469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 25473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25483e701f1cSksagiyam } 25493e701f1cSksagiyam 2550b08ad5deSksagiyam /*@ 2551a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2552b08ad5deSksagiyam 255320f4b53cSBarry Smith Collective 2554b08ad5deSksagiyam 2555b08ad5deSksagiyam Input Parameters: 2556a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2557a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 255820f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2559b08ad5deSksagiyam 2560b08ad5deSksagiyam Level: advanced 2561b08ad5deSksagiyam 2562a1cb98faSBarry Smith Note: 2563dc9a610eSPierre Jolivet The `PetscSF` argument must not be `NULL` if the `DM` is distributed, otherwise an error occurs. 2564e6368b79SVaclav Hapla 25651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2566a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2567b08ad5deSksagiyam @*/ 2568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2569d71ae5a4SJacob Faibussowitsch { 2570b08ad5deSksagiyam PetscBool ishdf5; 2571b08ad5deSksagiyam 2572b08ad5deSksagiyam PetscFunctionBegin; 2573b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2574b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2575e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 25769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2578b08ad5deSksagiyam if (ishdf5) { 2579b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2580b08ad5deSksagiyam PetscViewerFormat format; 2581b08ad5deSksagiyam 25829566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2583966bd95aSPierre 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]); 25849566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 2585b08ad5deSksagiyam #else 2586b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2587b08ad5deSksagiyam #endif 2588b08ad5deSksagiyam } 25899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 25903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2591b08ad5deSksagiyam } 2592b08ad5deSksagiyam 2593f84dd6b4Sksagiyam /*@ 2594a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2595f84dd6b4Sksagiyam 259620f4b53cSBarry Smith Collective 2597f84dd6b4Sksagiyam 2598f84dd6b4Sksagiyam Input Parameters: 2599a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2600a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 26010318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2602a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2603f84dd6b4Sksagiyam 2604a4e35b19SJacob Faibussowitsch Output Parameters: 260520f4b53cSBarry 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) 260620f4b53cSBarry 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) 2607f84dd6b4Sksagiyam 2608f84dd6b4Sksagiyam Level: advanced 2609f84dd6b4Sksagiyam 2610f84dd6b4Sksagiyam Notes: 261120f4b53cSBarry 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. 2612f84dd6b4Sksagiyam 26130318f8a0SStefano 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. 2614f84dd6b4Sksagiyam 261520f4b53cSBarry 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. 2616f84dd6b4Sksagiyam 2617f84dd6b4Sksagiyam Example using 2 processes: 2618a1cb98faSBarry Smith .vb 2619a1cb98faSBarry Smith NX (number of points on dm): 4 2620a1cb98faSBarry Smith sectionA : the on-disk section 2621a1cb98faSBarry Smith vecA : a vector associated with sectionA 2622a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2623a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2624a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2625f84dd6b4Sksagiyam 2626a1cb98faSBarry Smith rank 0 rank 1 2627a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2628a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2629a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2630a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2631a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2632a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2633a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2634a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2635a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2636a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2637a1cb98faSBarry Smith .ve 2638a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2639a1cb98faSBarry Smith 26401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2641f84dd6b4Sksagiyam @*/ 2642ce78bad3SBarry Smith PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, PeOp DM sectiondm, PetscSF globalToLocalPointSF, PeOp PetscSF *globalDofSF, PeOp PetscSF *localDofSF) 2643d71ae5a4SJacob Faibussowitsch { 2644f84dd6b4Sksagiyam PetscBool ishdf5; 2645f84dd6b4Sksagiyam 2646f84dd6b4Sksagiyam PetscFunctionBegin; 2647f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2648f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26490318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2650f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2651f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 26524f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 26534f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 26549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26559566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2656f84dd6b4Sksagiyam if (ishdf5) { 2657f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 26589566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2659f84dd6b4Sksagiyam #else 2660f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2661f84dd6b4Sksagiyam #endif 2662f84dd6b4Sksagiyam } 26639566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 26643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2665f84dd6b4Sksagiyam } 2666f84dd6b4Sksagiyam 26678be3dfe1Sksagiyam /*@ 26688be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 26698be3dfe1Sksagiyam 267020f4b53cSBarry Smith Collective 26718be3dfe1Sksagiyam 26728be3dfe1Sksagiyam Input Parameters: 2673a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2674a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26750318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2676a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26778be3dfe1Sksagiyam - vec - The global vector to set values of 26788be3dfe1Sksagiyam 26798be3dfe1Sksagiyam Level: advanced 26808be3dfe1Sksagiyam 26818be3dfe1Sksagiyam Notes: 26820318f8a0SStefano 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. 26838be3dfe1Sksagiyam 268460225df5SJacob Faibussowitsch Calling sequence: 2685a1cb98faSBarry Smith .vb 2686a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2687a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2688a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2689a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2690a1cb98faSBarry Smith DMClone(dm, §iondm); 2691a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2692a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2693a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2694a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2695a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2696a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2697a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2698a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2699a1cb98faSBarry Smith DMDestroy(§iondm); 2700a1cb98faSBarry Smith DMDestroy(&dm); 2701a1cb98faSBarry Smith .ve 27028be3dfe1Sksagiyam 27031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2704a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 27058be3dfe1Sksagiyam @*/ 2706d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2707d71ae5a4SJacob Faibussowitsch { 27088be3dfe1Sksagiyam PetscBool ishdf5; 27098be3dfe1Sksagiyam 27108be3dfe1Sksagiyam PetscFunctionBegin; 27118be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27128be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 27130318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 27148be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 27158be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 27168be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 27178be3dfe1Sksagiyam /* Check consistency */ 27188be3dfe1Sksagiyam { 27198be3dfe1Sksagiyam PetscSection section; 27208be3dfe1Sksagiyam PetscBool includesConstraints; 27218be3dfe1Sksagiyam PetscInt m, m1; 27228be3dfe1Sksagiyam 27239566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 27249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 27259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 27269566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 27279566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 272863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 27298be3dfe1Sksagiyam } 27309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 27319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 27328be3dfe1Sksagiyam if (ishdf5) { 27338be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 27349566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 27358be3dfe1Sksagiyam #else 27368be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 27378be3dfe1Sksagiyam #endif 27388be3dfe1Sksagiyam } 27399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 27403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27418be3dfe1Sksagiyam } 27428be3dfe1Sksagiyam 27438be3dfe1Sksagiyam /*@ 27448be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 27458be3dfe1Sksagiyam 274620f4b53cSBarry Smith Collective 27478be3dfe1Sksagiyam 27488be3dfe1Sksagiyam Input Parameters: 2749a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2750a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 27510318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2752a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 27538be3dfe1Sksagiyam - vec - The local vector to set values of 27548be3dfe1Sksagiyam 27558be3dfe1Sksagiyam Level: advanced 27568be3dfe1Sksagiyam 27578be3dfe1Sksagiyam Notes: 27580318f8a0SStefano 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. 27598be3dfe1Sksagiyam 276060225df5SJacob Faibussowitsch Calling sequence: 2761a1cb98faSBarry Smith .vb 2762a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2763a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2764a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2765a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2766a1cb98faSBarry Smith DMClone(dm, §iondm); 2767a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2768a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2769a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2770a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2771a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2772a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2773a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2774a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2775a1cb98faSBarry Smith DMDestroy(§iondm); 2776a1cb98faSBarry Smith DMDestroy(&dm); 2777a1cb98faSBarry Smith .ve 27788be3dfe1Sksagiyam 27791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2780a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 27818be3dfe1Sksagiyam @*/ 2782d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2783d71ae5a4SJacob Faibussowitsch { 27848be3dfe1Sksagiyam PetscBool ishdf5; 27858be3dfe1Sksagiyam 27868be3dfe1Sksagiyam PetscFunctionBegin; 27878be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27888be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 27890318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 27908be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 27918be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 27928be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 27938be3dfe1Sksagiyam /* Check consistency */ 27948be3dfe1Sksagiyam { 27958be3dfe1Sksagiyam PetscSection section; 27968be3dfe1Sksagiyam PetscBool includesConstraints; 27978be3dfe1Sksagiyam PetscInt m, m1; 27988be3dfe1Sksagiyam 27999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 28009566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 28019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 28029566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 28039566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 280463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 28058be3dfe1Sksagiyam } 28069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 28079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 28088be3dfe1Sksagiyam if (ishdf5) { 28098be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 28109566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 28118be3dfe1Sksagiyam #else 28128be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 28138be3dfe1Sksagiyam #endif 28148be3dfe1Sksagiyam } 28159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 28163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28178be3dfe1Sksagiyam } 28188be3dfe1Sksagiyam 2819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2820d71ae5a4SJacob Faibussowitsch { 2821552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2822552f7358SJed Brown 2823552f7358SJed Brown PetscFunctionBegin; 28249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 28259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 282601468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 282701468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", NULL)); 28289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 28299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 28302e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 28312e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 28322e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 28332e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 28346bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 28356bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2836adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2837adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2838adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2839adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2840c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2841c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2842d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2843d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 28445f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 28453ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 28469566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 28479566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 28489566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 28499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 28509566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 28519566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 285221027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 28539f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 28549566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 28559566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 28569566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 28571d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 28589566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 28599566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 28609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 28619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 28629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 28631fca310dSJames Wright if (mesh->periodic.face_sfs) { 28641fca310dSJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(PetscSFDestroy(&mesh->periodic.face_sfs[i])); 28651fca310dSJames Wright PetscCall(PetscFree(mesh->periodic.face_sfs)); 28661fca310dSJames Wright } 28676725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 2868b83f62b0SJames Wright if (mesh->periodic.periodic_points) { 2869b83f62b0SJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(ISDestroy(&mesh->periodic.periodic_points[i])); 2870b83f62b0SJames Wright PetscCall(PetscFree(mesh->periodic.periodic_points)); 2871b83f62b0SJames Wright } 28721fca310dSJames Wright if (mesh->periodic.transform) PetscCall(PetscFree(mesh->periodic.transform)); 28739566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 28749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 28759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 28769566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 28779566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 28789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 28799566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 28809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 28819566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 28829566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 28839566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2884c29ce622SStefano Zampini if (mesh->nonempty_comm != MPI_COMM_NULL && mesh->nonempty_comm != MPI_COMM_SELF) PetscCallMPI(MPI_Comm_free(&mesh->nonempty_comm)); 288561f058f9SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->transform)); 2886552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 28879566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 28883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2889552f7358SJed Brown } 2890552f7358SJed Brown 2891d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2892d71ae5a4SJacob Faibussowitsch { 2893d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2894acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 28959fca9976SJed Brown PetscInt localSize, localStart = 0; 2896837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2897b412c318SBarry Smith MatType mtype; 28981428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2899552f7358SJed Brown 2900552f7358SJed Brown PetscFunctionBegin; 29019566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2902b412c318SBarry Smith mtype = dm->mattype; 2903d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 29049566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 29059566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 29069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 29079fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 29089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 29099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 29109566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 29119566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 29129566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2913acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 29149566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 29159566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 29169566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 29179566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 29189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 29199566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 29209566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 29219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2922552f7358SJed Brown if (!isShell) { 29231c6742e7SMatthew G. Knepley // There are three states with pblocks, since block starts can have no dofs: 29241c6742e7SMatthew G. Knepley // UNKNOWN) New Block: An open block has been signalled by pblocks[p] == 1 29251c6742e7SMatthew G. Knepley // TRUE) Block Start: The first entry in a block has been added 29261c6742e7SMatthew G. Knepley // FALSE) Block Add: An additional block entry has been added, since pblocks[p] == 0 29271c6742e7SMatthew G. Knepley PetscBT blst; 29281c6742e7SMatthew G. Knepley PetscBool3 bstate = PETSC_BOOL3_UNKNOWN; 2929837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 29301c6742e7SMatthew G. Knepley const PetscInt *perm = NULL; 29319fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 29321c6742e7SMatthew G. Knepley PetscInt pStart, pEnd, dof, cdof, num_fields; 2933552f7358SJed Brown 29349566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 29351c6742e7SMatthew G. Knepley PetscCall(PetscSectionGetBlockStarts(sectionLocal, &blst)); 29361c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISGetIndices(sectionLocal->perm, &perm)); 29379fca9976SJed Brown 29389fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 29399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2940863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 29411c6742e7SMatthew G. Knepley // We need to process in the permuted order to get block sizes right 29421c6742e7SMatthew G. Knepley for (PetscInt point = pStart; point < pEnd; ++point) { 29431c6742e7SMatthew G. Knepley const PetscInt p = perm ? perm[point] : point; 29441c6742e7SMatthew G. Knepley 2945863027abSJed Brown switch (dm->blocking_type) { 29460e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 29479fca9976SJed Brown PetscInt bdof, offset; 2948a9d99c84SMatthew G. Knepley 29499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 29509fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 29519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 29521c6742e7SMatthew G. Knepley if (blst && PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_UNKNOWN; 295332b27637SMatthew G. Knepley if (dof > 0) { 29541c6742e7SMatthew G. Knepley // State change 29551c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_UNKNOWN) bstate = PETSC_BOOL3_TRUE; 29561c6742e7SMatthew G. Knepley else if (bstate == PETSC_BOOL3_TRUE && blst && !PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_FALSE; 29571c6742e7SMatthew G. Knepley 2958d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2959d02c7345SMatthew G. Knepley // Signal block concatenation 29601c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_FALSE && dof - cdof) pblocks[offset - localStart] = -(dof - cdof); 296132b27637SMatthew G. Knepley } 29621d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 29631d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 29641d17a0a3SMatthew G. Knepley if (dof) { 29659371c9d4SSatish Balay if (bs < 0) { 29669371c9d4SSatish Balay bs = bdof; 29679371c9d4SSatish Balay } else if (bs != bdof) { 29689371c9d4SSatish Balay bs = 1; 29699371c9d4SSatish Balay } 2970552f7358SJed Brown } 2971863027abSJed Brown } break; 2972863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2973863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2974863027abSJed Brown PetscInt num_comp, bdof, offset; 2975863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2976863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2977863027abSJed Brown if (dof < 0) continue; 2978863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2979863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2980863027abSJed 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); 2981863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2982863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2983863027abSJed Brown // Handle possibly constant block size (unlikely) 2984863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2985863027abSJed Brown if (dof) { 2986863027abSJed Brown if (bs < 0) { 2987863027abSJed Brown bs = bdof; 2988863027abSJed Brown } else if (bs != bdof) { 2989863027abSJed Brown bs = 1; 2990863027abSJed Brown } 2991863027abSJed Brown } 2992863027abSJed Brown } 2993863027abSJed Brown } break; 2994863027abSJed Brown } 29952a28c762SMatthew G Knepley } 29961c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISRestoreIndices(sectionLocal->perm, &perm)); 29972a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 29981690c2aeSBarry Smith bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs; 2999e432b41dSStefano Zampini bsLocal[1] = bs; 30009566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 3001e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 3002e432b41dSStefano Zampini else bs = bsMinMax[0]; 30036fd5c86aSStefano Zampini bs = PetscMax(1, bs); 30049566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 30050682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 30069566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 30079566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 30080682b8bbSJed Brown } else { 30099566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 30109566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 30119566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 3012552f7358SJed Brown } 301332b27637SMatthew G. Knepley if (pblocks) { // Consolidate blocks 30149fca9976SJed Brown PetscInt nblocks = 0; 301532b27637SMatthew G. Knepley pblocks[0] = PetscAbs(pblocks[0]); 30169fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 30179fca9976SJed Brown if (pblocks[i] == 0) continue; 3018d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 3019d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 3020d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 3021d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 3022d02c7345SMatthew G. Knepley } else { 30239fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 3024d02c7345SMatthew G. Knepley } 30251c6742e7SMatthew G. Knepley for (PetscInt j = 1; j < pblocks[i]; j++) 30261c6742e7SMatthew 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); 30279fca9976SJed Brown } 30289fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 30299fca9976SJed Brown } 30309fca9976SJed Brown PetscCall(PetscFree(pblocks)); 3031aa0f6e3cSJed Brown } 30329566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 30333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3034552f7358SJed Brown } 3035552f7358SJed Brown 30367cd05799SMatthew G. Knepley /*@ 3037a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 3038be36d101SStefano Zampini 3039a1cb98faSBarry Smith Not Collective 3040be36d101SStefano Zampini 3041be36d101SStefano Zampini Input Parameter: 304260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 3043be36d101SStefano Zampini 30442fe279fdSBarry Smith Output Parameter: 3045be36d101SStefano Zampini . subsection - The subdomain section 3046be36d101SStefano Zampini 3047be36d101SStefano Zampini Level: developer 3048be36d101SStefano Zampini 30491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 30507cd05799SMatthew G. Knepley @*/ 3051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 3052d71ae5a4SJacob Faibussowitsch { 3053be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 3054be36d101SStefano Zampini 3055be36d101SStefano Zampini PetscFunctionBegin; 3056be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3057be36d101SStefano Zampini if (!mesh->subdomainSection) { 3058be36d101SStefano Zampini PetscSection section; 3059be36d101SStefano Zampini PetscSF sf; 3060be36d101SStefano Zampini 30619566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 30629566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 3063eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 30649566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 3065be36d101SStefano Zampini } 3066be36d101SStefano Zampini *subsection = mesh->subdomainSection; 30673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3068be36d101SStefano Zampini } 3069be36d101SStefano Zampini 3070552f7358SJed Brown /*@ 307120f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 3072552f7358SJed Brown 3073a1cb98faSBarry Smith Not Collective 3074552f7358SJed Brown 3075552f7358SJed Brown Input Parameter: 307660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 3077552f7358SJed Brown 3078552f7358SJed Brown Output Parameters: 3079552f7358SJed Brown + pStart - The first mesh point 3080552f7358SJed Brown - pEnd - The upper bound for mesh points 3081552f7358SJed Brown 3082552f7358SJed Brown Level: beginner 3083552f7358SJed Brown 30841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 3085552f7358SJed Brown @*/ 3086d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 3087d71ae5a4SJacob Faibussowitsch { 3088552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3089552f7358SJed Brown 3090552f7358SJed Brown PetscFunctionBegin; 3091552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30929f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 30939f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 30943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3095552f7358SJed Brown } 3096552f7358SJed Brown 3097552f7358SJed Brown /*@ 309820f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 3099552f7358SJed Brown 3100a1cb98faSBarry Smith Not Collective 3101552f7358SJed Brown 3102552f7358SJed Brown Input Parameters: 310360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3104552f7358SJed Brown . pStart - The first mesh point 3105552f7358SJed Brown - pEnd - The upper bound for mesh points 3106552f7358SJed Brown 3107552f7358SJed Brown Level: beginner 3108552f7358SJed Brown 31091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 3110552f7358SJed Brown @*/ 3111d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 3112d71ae5a4SJacob Faibussowitsch { 3113552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3114552f7358SJed Brown 3115552f7358SJed Brown PetscFunctionBegin; 3116552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 31189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 311921027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 31203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3121552f7358SJed Brown } 3122552f7358SJed Brown 3123552f7358SJed Brown /*@ 3124eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 3125552f7358SJed Brown 3126a1cb98faSBarry Smith Not Collective 3127552f7358SJed Brown 3128552f7358SJed Brown Input Parameters: 312960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3130a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3131552f7358SJed Brown 3132552f7358SJed Brown Output Parameter: 313320f4b53cSBarry Smith . size - The cone size for point `p` 3134552f7358SJed Brown 3135552f7358SJed Brown Level: beginner 3136552f7358SJed Brown 31371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3138552f7358SJed Brown @*/ 3139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 3140d71ae5a4SJacob Faibussowitsch { 3141552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3142552f7358SJed Brown 3143552f7358SJed Brown PetscFunctionBegin; 3144552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31454f572ea9SToby Isaac PetscAssertPointer(size, 3); 31469f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 31479f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 31483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3149552f7358SJed Brown } 3150552f7358SJed Brown 3151552f7358SJed Brown /*@ 3152eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 3153552f7358SJed Brown 3154a1cb98faSBarry Smith Not Collective 3155552f7358SJed Brown 3156552f7358SJed Brown Input Parameters: 315760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3158a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 315920f4b53cSBarry Smith - size - The cone size for point `p` 3160552f7358SJed Brown 3161552f7358SJed Brown Level: beginner 3162552f7358SJed Brown 3163a1cb98faSBarry Smith Note: 3164a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3165a1cb98faSBarry Smith 31662c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3167552f7358SJed Brown @*/ 3168d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3169d71ae5a4SJacob Faibussowitsch { 3170552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3171552f7358SJed Brown 3172552f7358SJed Brown PetscFunctionBegin; 3173552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31749f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 31763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3177552f7358SJed Brown } 3178552f7358SJed Brown 3179552f7358SJed Brown /*@C 3180eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3181552f7358SJed Brown 3182a1cb98faSBarry Smith Not Collective 3183552f7358SJed Brown 3184552f7358SJed Brown Input Parameters: 3185a1cb98faSBarry Smith + dm - The `DMPLEX` 3186a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3187552f7358SJed Brown 3188552f7358SJed Brown Output Parameter: 31892c9a7b26SBarry Smith . cone - An array of points which are on the in-edges for point `p`, the length of `cone` is the result of `DMPlexGetConeSize()` 3190552f7358SJed Brown 3191552f7358SJed Brown Level: beginner 3192552f7358SJed Brown 319360225df5SJacob Faibussowitsch Fortran Notes: 31942c9a7b26SBarry Smith `cone` must be declared with 31952c9a7b26SBarry Smith .vb 31962c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 31972c9a7b26SBarry Smith .ve 31982c9a7b26SBarry Smith 3199feaf08eaSBarry Smith You must call `DMPlexRestoreCone()` after you finish using the array. 3200a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 32013813dfbdSMatthew G Knepley 32021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3203552f7358SJed Brown @*/ 3204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3205d71ae5a4SJacob Faibussowitsch { 3206552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3207552f7358SJed Brown PetscInt off; 3208552f7358SJed Brown 3209552f7358SJed Brown PetscFunctionBegin; 3210552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32114f572ea9SToby Isaac PetscAssertPointer(cone, 3); 32129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 32138e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 32143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3215552f7358SJed Brown } 3216552f7358SJed Brown 3217cc4c1da9SBarry Smith /*@ 32180ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 32190ce7577fSVaclav Hapla 3220a1cb98faSBarry Smith Not Collective 32210ce7577fSVaclav Hapla 32220ce7577fSVaclav Hapla Input Parameters: 3223a1cb98faSBarry Smith + dm - The `DMPLEX` 3224a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 32250ce7577fSVaclav Hapla 3226d8d19677SJose E. Roman Output Parameters: 322720f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 32282c9a7b26SBarry Smith - pCones - An `IS` containing the points which are on the in-edges for the point set `p` 32290ce7577fSVaclav Hapla 32300ce7577fSVaclav Hapla Level: intermediate 32310ce7577fSVaclav Hapla 32321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 32330ce7577fSVaclav Hapla @*/ 3234ce78bad3SBarry Smith PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PeOp PetscSection *pConesSection, PeOp IS *pCones) 3235d71ae5a4SJacob Faibussowitsch { 32360ce7577fSVaclav Hapla PetscSection cs, newcs; 32370ce7577fSVaclav Hapla PetscInt *cones; 32380ce7577fSVaclav Hapla PetscInt *newarr = NULL; 32390ce7577fSVaclav Hapla PetscInt n; 32400ce7577fSVaclav Hapla 32410ce7577fSVaclav Hapla PetscFunctionBegin; 32429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 32439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 32449566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 32450ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 32460ce7577fSVaclav Hapla if (pCones) { 32479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 32489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 32490ce7577fSVaclav Hapla } 32503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32510ce7577fSVaclav Hapla } 32520ce7577fSVaclav Hapla 3253af9eab45SVaclav Hapla /*@ 3254af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3255d4636a37SVaclav Hapla 3256a1cb98faSBarry Smith Not Collective 3257d4636a37SVaclav Hapla 3258d4636a37SVaclav Hapla Input Parameters: 3259a1cb98faSBarry Smith + dm - The `DMPLEX` 3260a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3261d4636a37SVaclav Hapla 3262d4636a37SVaclav Hapla Output Parameter: 32632c9a7b26SBarry Smith . expandedPoints - An `IS` containing the of vertices recursively expanded from input points 3264d4636a37SVaclav Hapla 3265d4636a37SVaclav Hapla Level: advanced 3266d4636a37SVaclav Hapla 3267af9eab45SVaclav Hapla Notes: 326820f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3269af9eab45SVaclav Hapla 3270a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3271a1cb98faSBarry Smith 32721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3273a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3274d4636a37SVaclav Hapla @*/ 3275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3276d71ae5a4SJacob Faibussowitsch { 3277af9eab45SVaclav Hapla IS *expandedPointsAll; 3278af9eab45SVaclav Hapla PetscInt depth; 3279d4636a37SVaclav Hapla 3280d4636a37SVaclav Hapla PetscFunctionBegin; 3281af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3282af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 32834f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 32849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3285af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 32869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 32879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 32883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3289af9eab45SVaclav Hapla } 3290af9eab45SVaclav Hapla 3291af9eab45SVaclav Hapla /*@ 32922c9a7b26SBarry Smith DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices 32932c9a7b26SBarry Smith (DAG points of depth 0, i.e., without cones). 3294af9eab45SVaclav Hapla 3295a1cb98faSBarry Smith Not Collective 3296af9eab45SVaclav Hapla 3297af9eab45SVaclav Hapla Input Parameters: 3298a1cb98faSBarry Smith + dm - The `DMPLEX` 3299a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3300af9eab45SVaclav Hapla 3301d8d19677SJose E. Roman Output Parameters: 3302a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3303af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3304af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3305af9eab45SVaclav Hapla 3306af9eab45SVaclav Hapla Level: advanced 3307af9eab45SVaclav Hapla 3308af9eab45SVaclav Hapla Notes: 3309a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3310af9eab45SVaclav Hapla 3311a4e35b19SJacob 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. 3312af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3313af9eab45SVaclav Hapla 3314a4e35b19SJacob 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\: 3315a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3316a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3317af9eab45SVaclav Hapla 33181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3319a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3320af9eab45SVaclav Hapla @*/ 3321ce78bad3SBarry Smith PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PeOp PetscInt *depth, PeOp IS *expandedPoints[], PeOp PetscSection *sections[]) 3322d71ae5a4SJacob Faibussowitsch { 3323af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3324af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3325af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3326af9eab45SVaclav Hapla IS *expandedPoints_; 3327af9eab45SVaclav Hapla PetscSection *sections_; 3328af9eab45SVaclav Hapla 3329af9eab45SVaclav Hapla PetscFunctionBegin; 3330af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3331af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 33324f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 33334f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 33344f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 33359566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 33369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 33379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 33389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 33399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3340af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3341af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 33429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 33439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3344af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 33459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3346af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 33479566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 33489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3349af9eab45SVaclav Hapla } else { 33509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3351af9eab45SVaclav Hapla } 3352af9eab45SVaclav Hapla } 33539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 33549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 33559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3356af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 33579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 33589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3359af9eab45SVaclav Hapla if (cn > 1) { 33609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 3361418fb43bSPierre Jolivet PetscCall(PetscArraycpy(&newarr[co], cone, cn)); 3362af9eab45SVaclav Hapla } else { 3363af9eab45SVaclav Hapla newarr[co] = arr[i]; 3364af9eab45SVaclav Hapla } 3365af9eab45SVaclav Hapla } 33669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3367af9eab45SVaclav Hapla arr = newarr; 3368af9eab45SVaclav Hapla n = newn; 3369af9eab45SVaclav Hapla } 33709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3371af9eab45SVaclav Hapla *depth = depth_; 3372af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3373af9eab45SVaclav Hapla else { 33749566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 33759566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3376af9eab45SVaclav Hapla } 3377af9eab45SVaclav Hapla if (sections) *sections = sections_; 3378af9eab45SVaclav Hapla else { 33799566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 33809566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3381af9eab45SVaclav Hapla } 33823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3383af9eab45SVaclav Hapla } 3384af9eab45SVaclav Hapla 3385af9eab45SVaclav Hapla /*@ 3386a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3387af9eab45SVaclav Hapla 3388a1cb98faSBarry Smith Not Collective 3389af9eab45SVaclav Hapla 3390af9eab45SVaclav Hapla Input Parameters: 3391a1cb98faSBarry Smith + dm - The `DMPLEX` 3392a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3393af9eab45SVaclav Hapla 3394d8d19677SJose E. Roman Output Parameters: 3395a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3396af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3397af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3398af9eab45SVaclav Hapla 3399af9eab45SVaclav Hapla Level: advanced 3400af9eab45SVaclav Hapla 3401a1cb98faSBarry Smith Note: 3402a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3403af9eab45SVaclav Hapla 34041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3405a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3406af9eab45SVaclav Hapla @*/ 3407ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PeOp PetscInt *depth, PeOp IS *expandedPoints[], PeOp PetscSection *sections[]) 3408d71ae5a4SJacob Faibussowitsch { 3409af9eab45SVaclav Hapla PetscInt d, depth_; 3410af9eab45SVaclav Hapla 3411af9eab45SVaclav Hapla PetscFunctionBegin; 34129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 34131dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3414af9eab45SVaclav Hapla if (depth) *depth = 0; 3415af9eab45SVaclav Hapla if (expandedPoints) { 341657508eceSPierre Jolivet for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&(*expandedPoints)[d])); 34179566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3418af9eab45SVaclav Hapla } 3419af9eab45SVaclav Hapla if (sections) { 342057508eceSPierre Jolivet for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&(*sections)[d])); 34219566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3422af9eab45SVaclav Hapla } 34233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3424d4636a37SVaclav Hapla } 3425d4636a37SVaclav Hapla 3426552f7358SJed Brown /*@ 342792371b87SBarry 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 3428552f7358SJed Brown 3429a1cb98faSBarry Smith Not Collective 3430552f7358SJed Brown 3431552f7358SJed Brown Input Parameters: 343260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3433a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34342c9a7b26SBarry Smith - cone - An array of points which are on the in-edges for point `p`, its length must have been previously provided with `DMPlexSetConeSize()` 3435552f7358SJed Brown 3436552f7358SJed Brown Level: beginner 3437552f7358SJed Brown 3438a1cb98faSBarry Smith Note: 3439a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3440a1cb98faSBarry Smith 34411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3442552f7358SJed Brown @*/ 3443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3444d71ae5a4SJacob Faibussowitsch { 3445552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3446552f7358SJed Brown PetscInt dof, off, c; 3447552f7358SJed Brown 3448552f7358SJed Brown PetscFunctionBegin; 3449552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34514f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 34529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3453db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3454db485b19SStefano Zampini PetscInt pStart, pEnd; 3455db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345663a3b9bcSJacob 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); 3457552f7358SJed Brown for (c = 0; c < dof; ++c) { 345863a3b9bcSJacob 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); 3459552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3460552f7358SJed Brown } 3461db485b19SStefano Zampini } else { 3462db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3463db485b19SStefano Zampini } 34643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3465552f7358SJed Brown } 3466552f7358SJed Brown 3467552f7358SJed Brown /*@C 3468eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3469552f7358SJed Brown 3470a1cb98faSBarry Smith Not Collective 3471552f7358SJed Brown 3472552f7358SJed Brown Input Parameters: 347360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3474a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3475552f7358SJed Brown 3476552f7358SJed Brown Output Parameter: 347720f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 34782c9a7b26SBarry Smith integer giving the prescription for cone traversal. Its length is given by the result of `DMPlexSetConeSize()` 3479552f7358SJed Brown 3480552f7358SJed Brown Level: beginner 3481552f7358SJed Brown 3482a1cb98faSBarry Smith Note: 3483b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3484b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3485a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3486b5a892a1SMatthew G. Knepley with the identity. 3487b5a892a1SMatthew G. Knepley 348860225df5SJacob Faibussowitsch Fortran Notes: 34892c9a7b26SBarry Smith You must call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3490a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 34913813dfbdSMatthew G Knepley 34922c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetConeSize()`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, 34932c9a7b26SBarry Smith `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3494552f7358SJed Brown @*/ 3495d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3496d71ae5a4SJacob Faibussowitsch { 3497552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3498552f7358SJed Brown PetscInt off; 3499552f7358SJed Brown 3500552f7358SJed Brown PetscFunctionBegin; 3501552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 350276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3503552f7358SJed Brown PetscInt dof; 35049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35054f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3506552f7358SJed Brown } 35079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35080d644c17SKarl Rupp 3509552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 35103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3511552f7358SJed Brown } 3512552f7358SJed Brown 3513552f7358SJed Brown /*@ 3514eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3515552f7358SJed Brown 3516a1cb98faSBarry Smith Not Collective 3517552f7358SJed Brown 3518552f7358SJed Brown Input Parameters: 351960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3520a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35212c9a7b26SBarry Smith - coneOrientation - An array of orientations. Its length is given by the result of `DMPlexSetConeSize()` 3522b5a892a1SMatthew G. Knepley 3523552f7358SJed Brown Level: beginner 3524552f7358SJed Brown 3525a1cb98faSBarry Smith Notes: 3526a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3527a1cb98faSBarry Smith 3528a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3529a1cb98faSBarry Smith 35301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3531552f7358SJed Brown @*/ 3532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3533d71ae5a4SJacob Faibussowitsch { 3534552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3535552f7358SJed Brown PetscInt pStart, pEnd; 3536552f7358SJed Brown PetscInt dof, off, c; 3537552f7358SJed Brown 3538552f7358SJed Brown PetscFunctionBegin; 3539552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35414f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 35429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3543db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3544db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 354563a3b9bcSJacob 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); 3546552f7358SJed Brown for (c = 0; c < dof; ++c) { 3547552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3548552f7358SJed Brown 35499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 35501dca8a05SBarry 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); 3551552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3552552f7358SJed Brown } 3553db485b19SStefano Zampini } else { 3554db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3555db485b19SStefano Zampini } 35563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3557552f7358SJed Brown } 3558552f7358SJed Brown 35597cd05799SMatthew G. Knepley /*@ 3560eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 35617cd05799SMatthew G. Knepley 3562a1cb98faSBarry Smith Not Collective 35637cd05799SMatthew G. Knepley 35647cd05799SMatthew G. Knepley Input Parameters: 356560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3566a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35677cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 35687cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 35697cd05799SMatthew G. Knepley 35707cd05799SMatthew G. Knepley Level: beginner 35717cd05799SMatthew G. Knepley 35721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 35737cd05799SMatthew G. Knepley @*/ 3574d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3575d71ae5a4SJacob Faibussowitsch { 3576552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3577552f7358SJed Brown PetscInt pStart, pEnd; 3578552f7358SJed Brown PetscInt dof, off; 3579552f7358SJed Brown 3580552f7358SJed Brown PetscFunctionBegin; 3581552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3582a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 35839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 358463a3b9bcSJacob 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); 358563a3b9bcSJacob 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); 35869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 358763a3b9bcSJacob 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); 3588a03d55ffSStefano Zampini } 3589a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3590552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 35913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3592552f7358SJed Brown } 3593552f7358SJed Brown 35947cd05799SMatthew G. Knepley /*@ 3595eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 35967cd05799SMatthew G. Knepley 3597a1cb98faSBarry Smith Not Collective 35987cd05799SMatthew G. Knepley 35997cd05799SMatthew G. Knepley Input Parameters: 360060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3601a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36027cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 36037cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 36047cd05799SMatthew G. Knepley 36057cd05799SMatthew G. Knepley Level: beginner 36067cd05799SMatthew G. Knepley 3607a1cb98faSBarry Smith Note: 3608a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3609b5a892a1SMatthew G. Knepley 36101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36117cd05799SMatthew G. Knepley @*/ 3612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3613d71ae5a4SJacob Faibussowitsch { 361477c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 361577c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 361677c88f5bSMatthew G Knepley PetscInt dof, off; 361777c88f5bSMatthew G Knepley 361877c88f5bSMatthew G Knepley PetscFunctionBegin; 361977c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3620a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 36219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 362263a3b9bcSJacob 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); 36239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 362463a3b9bcSJacob 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); 3625a03d55ffSStefano Zampini } 3626a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 362777c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 36283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 362977c88f5bSMatthew G Knepley } 363077c88f5bSMatthew G Knepley 36319f4ada15SMatthew G. Knepley /*@C 36329f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 36339f4ada15SMatthew G. Knepley 36349f4ada15SMatthew G. Knepley Not collective 36359f4ada15SMatthew G. Knepley 36369f4ada15SMatthew G. Knepley Input Parameters: 36379f4ada15SMatthew G. Knepley + dm - The DMPlex 36389f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 36399f4ada15SMatthew G. Knepley 36409f4ada15SMatthew G. Knepley Output Parameters: 364120f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 364220f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 36439f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 36449f4ada15SMatthew G. Knepley 36459f4ada15SMatthew G. Knepley Level: beginner 36469f4ada15SMatthew G. Knepley 36479f4ada15SMatthew G. Knepley Notes: 36489f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 36499f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 365020f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 36519f4ada15SMatthew G. Knepley with the identity. 36529f4ada15SMatthew G. Knepley 36532c9a7b26SBarry Smith You must also call `DMPlexRestoreOrientedCone()` after you finish using the returned array. 36542c9a7b26SBarry Smith 36559f4ada15SMatthew G. Knepley Fortran Notes: 36562c9a7b26SBarry Smith `cone` and `ornt` must be declared with 36572c9a7b26SBarry Smith .vb 36582c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 36592c9a7b26SBarry Smith PetscInt, pointer :: ornt(:) 36602c9a7b26SBarry Smith .ve 36619f4ada15SMatthew G. Knepley 36621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 36639f4ada15SMatthew G. Knepley @*/ 3664ce78bad3SBarry Smith PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, PeOp const PetscInt *cone[], PeOp const PetscInt *ornt[]) 36659f4ada15SMatthew G. Knepley { 36669f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 36679f4ada15SMatthew G. Knepley 36689f4ada15SMatthew G. Knepley PetscFunctionBegin; 36699f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36709f4ada15SMatthew G. Knepley if (mesh->tr) { 36719f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 36729f4ada15SMatthew G. Knepley } else { 36739f4ada15SMatthew G. Knepley PetscInt off; 36749f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 36759f4ada15SMatthew G. Knepley PetscInt dof; 36769f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 36779f4ada15SMatthew G. Knepley if (dof) { 36784f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 36794f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 36809f4ada15SMatthew G. Knepley } 36819f4ada15SMatthew G. Knepley } 36829f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 36838e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 36848e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 36859f4ada15SMatthew G. Knepley } 36863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36879f4ada15SMatthew G. Knepley } 36889f4ada15SMatthew G. Knepley 36899f4ada15SMatthew G. Knepley /*@C 36902c9a7b26SBarry Smith DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG obtained with `DMPlexGetOrientedCone()` 36919f4ada15SMatthew G. Knepley 369220f4b53cSBarry Smith Not Collective 36939f4ada15SMatthew G. Knepley 36949f4ada15SMatthew G. Knepley Input Parameters: 36959f4ada15SMatthew G. Knepley + dm - The DMPlex 369620f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36979f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 369820f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 36999f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 37009f4ada15SMatthew G. Knepley 37019f4ada15SMatthew G. Knepley Level: beginner 37029f4ada15SMatthew G. Knepley 37031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 37049f4ada15SMatthew G. Knepley @*/ 37059f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 37069f4ada15SMatthew G. Knepley { 37079f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 37089f4ada15SMatthew G. Knepley 37099f4ada15SMatthew G. Knepley PetscFunctionBegin; 37109f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37119f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 37123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37139f4ada15SMatthew G. Knepley } 37149f4ada15SMatthew G. Knepley 3715552f7358SJed Brown /*@ 3716eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3717552f7358SJed Brown 3718a1cb98faSBarry Smith Not Collective 3719552f7358SJed Brown 3720552f7358SJed Brown Input Parameters: 372160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3722a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3723552f7358SJed Brown 3724552f7358SJed Brown Output Parameter: 372520f4b53cSBarry Smith . size - The support size for point `p` 3726552f7358SJed Brown 3727552f7358SJed Brown Level: beginner 3728552f7358SJed Brown 37291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3730552f7358SJed Brown @*/ 3731d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3732d71ae5a4SJacob Faibussowitsch { 3733552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3734552f7358SJed Brown 3735552f7358SJed Brown PetscFunctionBegin; 3736552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37374f572ea9SToby Isaac PetscAssertPointer(size, 3); 37389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 37393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3740552f7358SJed Brown } 3741552f7358SJed Brown 3742552f7358SJed Brown /*@ 3743eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3744552f7358SJed Brown 3745a1cb98faSBarry Smith Not Collective 3746552f7358SJed Brown 3747552f7358SJed Brown Input Parameters: 374860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3749a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 375020f4b53cSBarry Smith - size - The support size for point `p` 3751552f7358SJed Brown 3752a1cb98faSBarry Smith Level: beginner 3753552f7358SJed Brown 3754552f7358SJed Brown Note: 375520f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3756552f7358SJed Brown 37571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3758552f7358SJed Brown @*/ 3759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3760d71ae5a4SJacob Faibussowitsch { 3761552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3762552f7358SJed Brown 3763552f7358SJed Brown PetscFunctionBegin; 3764552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 37663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3767552f7358SJed Brown } 3768552f7358SJed Brown 3769552f7358SJed Brown /*@C 3770eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3771552f7358SJed Brown 3772a1cb98faSBarry Smith Not Collective 3773552f7358SJed Brown 3774552f7358SJed Brown Input Parameters: 377560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3776a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3777552f7358SJed Brown 3778552f7358SJed Brown Output Parameter: 37792c9a7b26SBarry Smith . support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3780552f7358SJed Brown 3781552f7358SJed Brown Level: beginner 3782552f7358SJed Brown 378360225df5SJacob Faibussowitsch Fortran Notes: 37842c9a7b26SBarry Smith `support` must be declared with 37852c9a7b26SBarry Smith .vb 37862c9a7b26SBarry Smith PetscInt, pointer :: support(:) 37872c9a7b26SBarry Smith .ve 37882c9a7b26SBarry Smith 3789a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3790a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 37913813dfbdSMatthew G Knepley 37921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3793552f7358SJed Brown @*/ 3794d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3795d71ae5a4SJacob Faibussowitsch { 3796552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3797552f7358SJed Brown PetscInt off; 3798552f7358SJed Brown 3799552f7358SJed Brown PetscFunctionBegin; 3800552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38014f572ea9SToby Isaac PetscAssertPointer(support, 3); 38029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 38038e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 38043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3805552f7358SJed Brown } 3806552f7358SJed Brown 3807552f7358SJed Brown /*@ 380892371b87SBarry 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 3809552f7358SJed Brown 3810a1cb98faSBarry Smith Not Collective 3811552f7358SJed Brown 3812552f7358SJed Brown Input Parameters: 381360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3814a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 38152c9a7b26SBarry Smith - support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3816552f7358SJed Brown 3817552f7358SJed Brown Level: beginner 3818552f7358SJed Brown 3819a1cb98faSBarry Smith Note: 3820a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3821a1cb98faSBarry Smith 38221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3823552f7358SJed Brown @*/ 3824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3825d71ae5a4SJacob Faibussowitsch { 3826552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3827552f7358SJed Brown PetscInt pStart, pEnd; 3828552f7358SJed Brown PetscInt dof, off, c; 3829552f7358SJed Brown 3830552f7358SJed Brown PetscFunctionBegin; 3831552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 38339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 38344f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 38359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 383663a3b9bcSJacob 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); 3837552f7358SJed Brown for (c = 0; c < dof; ++c) { 383863a3b9bcSJacob 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); 3839552f7358SJed Brown mesh->supports[off + c] = support[c]; 3840552f7358SJed Brown } 38413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3842552f7358SJed Brown } 3843552f7358SJed Brown 38447cd05799SMatthew G. Knepley /*@ 3845eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 38467cd05799SMatthew G. Knepley 3847a1cb98faSBarry Smith Not Collective 38487cd05799SMatthew G. Knepley 38497cd05799SMatthew G. Knepley Input Parameters: 385060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3851a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 38527cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 38537cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 38547cd05799SMatthew G. Knepley 38557cd05799SMatthew G. Knepley Level: beginner 38567cd05799SMatthew G. Knepley 38571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 38587cd05799SMatthew G. Knepley @*/ 3859d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3860d71ae5a4SJacob Faibussowitsch { 3861552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3862552f7358SJed Brown PetscInt pStart, pEnd; 3863552f7358SJed Brown PetscInt dof, off; 3864552f7358SJed Brown 3865552f7358SJed Brown PetscFunctionBegin; 3866552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 38679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 38689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 38699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 387063a3b9bcSJacob 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); 387163a3b9bcSJacob 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); 387263a3b9bcSJacob 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); 3873552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 38743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3875552f7358SJed Brown } 3876552f7358SJed Brown 3877b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3878d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3879d71ae5a4SJacob Faibussowitsch { 3880b5a892a1SMatthew G. Knepley switch (ct) { 3881b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3882b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3883b5a892a1SMatthew G. Knepley break; 3884b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3885b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3886b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3887b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3888b5a892a1SMatthew G. Knepley break; 3889b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3890b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3891b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3892b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3893b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3894b5a892a1SMatthew G. Knepley break; 3895d71ae5a4SJacob Faibussowitsch default: 3896d71ae5a4SJacob Faibussowitsch return o; 3897b5a892a1SMatthew G. Knepley } 3898b5a892a1SMatthew G. Knepley return o; 3899b5a892a1SMatthew G. Knepley } 3900b5a892a1SMatthew G. Knepley 3901b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3902d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3903d71ae5a4SJacob Faibussowitsch { 3904b5a892a1SMatthew G. Knepley switch (ct) { 3905b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3906b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3907b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3908b5a892a1SMatthew G. Knepley break; 3909b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3910b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3911b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3912b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3913b5a892a1SMatthew G. Knepley break; 3914b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3915b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3916b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3917b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3918b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3919b5a892a1SMatthew G. Knepley break; 3920d71ae5a4SJacob Faibussowitsch default: 3921d71ae5a4SJacob Faibussowitsch return o; 3922b5a892a1SMatthew G. Knepley } 3923b5a892a1SMatthew G. Knepley return o; 3924b5a892a1SMatthew G. Knepley } 3925b5a892a1SMatthew G. Knepley 3926b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3928d71ae5a4SJacob Faibussowitsch { 3929b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3930b5a892a1SMatthew G. Knepley 3931b5a892a1SMatthew G. Knepley PetscFunctionBegin; 39329566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3933b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3934b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3935b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3936b5a892a1SMatthew G. Knepley 39379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 39389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 39399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3940b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3941b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3942b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3943b5a892a1SMatthew G. Knepley 39449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3945b5a892a1SMatthew G. Knepley switch (ct) { 3946b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 39479566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39489566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3949b5a892a1SMatthew G. Knepley break; 3950b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 39519566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 39529566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39539566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3954b5a892a1SMatthew G. Knepley break; 3955b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 39569566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 39579566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 39589566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 39599566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3960b5a892a1SMatthew G. Knepley break; 3961d71ae5a4SJacob Faibussowitsch default: 3962d71ae5a4SJacob Faibussowitsch break; 3963b5a892a1SMatthew G. Knepley } 3964b5a892a1SMatthew G. Knepley } 3965b5a892a1SMatthew G. Knepley } 39663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3967b5a892a1SMatthew G. Knepley } 3968b5a892a1SMatthew G. Knepley 396909015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 397009015e70SStefano Zampini { 397109015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 397209015e70SStefano Zampini 397309015e70SStefano Zampini PetscFunctionBeginHot; 397409015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 397509015e70SStefano Zampini if (useCone) { 397609015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 397709015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 397809015e70SStefano Zampini } else { 397909015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 398009015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 398109015e70SStefano Zampini } 398209015e70SStefano Zampini } else { 398309015e70SStefano Zampini if (useCone) { 398409015e70SStefano Zampini const PetscSection s = mesh->coneSection; 398509015e70SStefano Zampini const PetscInt ps = p - s->pStart; 398609015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 398709015e70SStefano Zampini 398809015e70SStefano Zampini *size = s->atlasDof[ps]; 398909015e70SStefano Zampini *arr = mesh->cones + off; 399009015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 399109015e70SStefano Zampini } else { 399209015e70SStefano Zampini const PetscSection s = mesh->supportSection; 399309015e70SStefano Zampini const PetscInt ps = p - s->pStart; 399409015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 399509015e70SStefano Zampini 399609015e70SStefano Zampini *size = s->atlasDof[ps]; 399709015e70SStefano Zampini *arr = mesh->supports + off; 399809015e70SStefano Zampini } 399909015e70SStefano Zampini } 400009015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 400109015e70SStefano Zampini } 400209015e70SStefano Zampini 400309015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 400409015e70SStefano Zampini { 400509015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 400609015e70SStefano Zampini 400709015e70SStefano Zampini PetscFunctionBeginHot; 400809015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 400909015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 401009015e70SStefano Zampini } 401109015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 401209015e70SStefano Zampini } 401309015e70SStefano Zampini 4014d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4015d71ae5a4SJacob Faibussowitsch { 4016b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4017b5a892a1SMatthew G. Knepley PetscInt *closure; 4018b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 4019b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 4020b5a892a1SMatthew G. Knepley 4021b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4022b5a892a1SMatthew G. Knepley if (ornt) { 40239566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4024476787b7SMatthew 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; 4025b5a892a1SMatthew G. Knepley } 4026b5a892a1SMatthew G. Knepley if (*points) { 4027b5a892a1SMatthew G. Knepley closure = *points; 4028b5a892a1SMatthew G. Knepley } else { 4029b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 40309566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 40319566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 4032b5a892a1SMatthew G. Knepley } 403309015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 4034b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 4035b5a892a1SMatthew G. Knepley closure[off++] = p; 4036b5a892a1SMatthew G. Knepley closure[off++] = 0; 4037b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4038b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 4039b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 4040b5a892a1SMatthew G. Knepley } 4041b5a892a1SMatthew G. Knepley } else { 404285036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 4043b5a892a1SMatthew G. Knepley 4044b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 4045b5a892a1SMatthew G. Knepley closure[off++] = p; 4046b5a892a1SMatthew G. Knepley closure[off++] = ornt; 4047b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4048b5a892a1SMatthew G. Knepley DMPolytopeType ft; 4049b5a892a1SMatthew G. Knepley 40509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 4051b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 4052b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 4053b5a892a1SMatthew G. Knepley } 4054b5a892a1SMatthew G. Knepley } 405509015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 4056b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 4057b5a892a1SMatthew G. Knepley if (points) *points = closure; 40583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4059b5a892a1SMatthew G. Knepley } 4060b5a892a1SMatthew G. Knepley 4061d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 4062d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 4063d71ae5a4SJacob Faibussowitsch { 406485036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 4065b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 4066b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 4067b5a892a1SMatthew G. Knepley DMPolytopeType ft; 4068b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 4069b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 4070b5a892a1SMatthew G. Knepley 4071b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 40729566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 407309015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 40749566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4075b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 4076b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 4077b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 40789371c9d4SSatish Balay if (*points) { 40799371c9d4SSatish Balay pts = *points; 40809371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 4081b5a892a1SMatthew G. Knepley c = 0; 4082b5a892a1SMatthew G. Knepley pts[c++] = point; 4083b5a892a1SMatthew G. Knepley pts[c++] = o; 40849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 40859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 40869371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40879371c9d4SSatish Balay pts[c++] = closure[cl]; 40889371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40899371c9d4SSatish Balay } 40909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 40919371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40929371c9d4SSatish Balay pts[c++] = closure[cl]; 40939371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40949371c9d4SSatish Balay } 40959566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 4096b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 40979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 4098b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 4099b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 4100b5a892a1SMatthew G. Knepley } 410109015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 4102b5a892a1SMatthew G. Knepley if (dim >= 3) { 4103b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 4104b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 4105b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 4106b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 4107b5a892a1SMatthew G. Knepley 41089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 410985036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 411009015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4111b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 4112b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 4113b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 4114b5a892a1SMatthew G. Knepley 41159371c9d4SSatish Balay for (i = 0; i < c; i += 2) 41169371c9d4SSatish Balay if (pts[i] == cp) break; 4117b5a892a1SMatthew G. Knepley if (i == c) { 41189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 4119b5a892a1SMatthew G. Knepley pts[c++] = cp; 4120b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 4121b5a892a1SMatthew G. Knepley } 4122b5a892a1SMatthew G. Knepley } 412309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4124b5a892a1SMatthew G. Knepley } 4125b5a892a1SMatthew G. Knepley } 4126b5a892a1SMatthew G. Knepley *numPoints = c / 2; 4127b5a892a1SMatthew G. Knepley *points = pts; 41283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4129b5a892a1SMatthew G. Knepley } 4130b5a892a1SMatthew G. Knepley 4131d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4132d71ae5a4SJacob Faibussowitsch { 4133b5a892a1SMatthew G. Knepley DMPolytopeType ct; 4134b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 4135b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 4136b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 4137b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 4138b5a892a1SMatthew G. Knepley 4139b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 41409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4141b5a892a1SMatthew G. Knepley if (depth == 1) { 41429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 41433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4144b5a892a1SMatthew G. Knepley } 41459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4146476787b7SMatthew 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; 4147c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 41489566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 41493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4150b5a892a1SMatthew G. Knepley } 41519566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4152b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 4153b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 4154b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 41559566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 41569371c9d4SSatish Balay if (*points) { 41579371c9d4SSatish Balay closure = *points; 41589371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 4159b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 4160b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 4161b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 4162b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 4163b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4164b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 4165b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 4166b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 4167b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 4168b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 416985036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 417009015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4171b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4172b5a892a1SMatthew G. Knepley 4173b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 417485036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 417563a3b9bcSJacob 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); 4176b5a892a1SMatthew G. Knepley } 417709015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4178b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4179b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4180b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4181b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 41829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4183b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4184b5a892a1SMatthew G. Knepley PetscInt c; 4185b5a892a1SMatthew G. Knepley 4186b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4187b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4188b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4189b5a892a1SMatthew G. Knepley } 4190b5a892a1SMatthew G. Knepley if (c == closureSize) { 4191b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4192b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4193b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4194b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4195b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4196b5a892a1SMatthew G. Knepley } 4197b5a892a1SMatthew G. Knepley } 419809015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4199b5a892a1SMatthew G. Knepley } 42009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4201b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4202b5a892a1SMatthew G. Knepley if (points) *points = closure; 42033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4204b5a892a1SMatthew G. Knepley } 4205b5a892a1SMatthew G. Knepley 4206552f7358SJed Brown /*@C 4207eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4208552f7358SJed Brown 4209a1cb98faSBarry Smith Not Collective 4210552f7358SJed Brown 4211552f7358SJed Brown Input Parameters: 4212a1cb98faSBarry Smith + dm - The `DMPLEX` 4213b5a892a1SMatthew G. Knepley . p - The mesh point 4214*7d8e5ce9SJames Wright - useCone - `PETSC_TRUE` for the closure, otherwise return the support 4215552f7358SJed Brown 42166b867d5aSJose E. Roman Input/Output Parameter: 42176b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 42182c9a7b26SBarry Smith if *points is `NULL` on input, internal storage will be returned, use `DMPlexRestoreTransitiveClosure()`, 42192c9a7b26SBarry Smith otherwise the provided array is used to hold the values 42206b867d5aSJose E. Roman 42216b867d5aSJose E. Roman Output Parameter: 42222c9a7b26SBarry Smith . numPoints - The number of points in the closure, so `points` is of size 2*`numPoints` 4223552f7358SJed Brown 4224a1cb98faSBarry Smith Level: beginner 4225a1cb98faSBarry Smith 4226552f7358SJed Brown Note: 422720f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4228552f7358SJed Brown 422960225df5SJacob Faibussowitsch Fortran Notes: 42302c9a7b26SBarry Smith `points` must be declared with 42312c9a7b26SBarry Smith .vb 42322c9a7b26SBarry Smith PetscInt, pointer :: points(:) 42332c9a7b26SBarry Smith .ve 42342c9a7b26SBarry Smith and is always allocated by the function. 42352c9a7b26SBarry Smith 4236feaf08eaSBarry Smith Pass `PETSC_NULL_INTEGER` for `numPoints` if it is not needed 42373813dfbdSMatthew G Knepley 42381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4239552f7358SJed Brown @*/ 4240d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4241d71ae5a4SJacob Faibussowitsch { 4242b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4243552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42444f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 42454f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 4246332e0eaaSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 4247332e0eaaSMatthew G. Knepley PetscInt pStart, pEnd; 4248332e0eaaSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4249332e0eaaSMatthew 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); 4250332e0eaaSMatthew G. Knepley } 42519566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 42523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42539bf0dad6SMatthew G. Knepley } 42549bf0dad6SMatthew G. Knepley 4255552f7358SJed Brown /*@C 4256eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4257552f7358SJed Brown 4258a1cb98faSBarry Smith Not Collective 4259552f7358SJed Brown 4260552f7358SJed Brown Input Parameters: 4261a1cb98faSBarry Smith + dm - The `DMPLEX` 4262b5a892a1SMatthew G. Knepley . p - The mesh point 4263a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 426420f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4265b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4266552f7358SJed Brown 4267a1cb98faSBarry Smith Level: beginner 4268a1cb98faSBarry Smith 4269552f7358SJed Brown Note: 427020f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4271552f7358SJed Brown 42721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4273552f7358SJed Brown @*/ 4274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4275d71ae5a4SJacob Faibussowitsch { 4276b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4277552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42784ff43b2cSJed Brown if (numPoints) *numPoints = 0; 42799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 42803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4281552f7358SJed Brown } 4282552f7358SJed Brown 4283552f7358SJed Brown /*@ 4284eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4285552f7358SJed Brown 4286a1cb98faSBarry Smith Not Collective 4287552f7358SJed Brown 4288552f7358SJed Brown Input Parameter: 428960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4290552f7358SJed Brown 4291552f7358SJed Brown Output Parameters: 4292552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4293552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4294552f7358SJed Brown 4295552f7358SJed Brown Level: beginner 4296552f7358SJed Brown 42971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4298552f7358SJed Brown @*/ 4299ce78bad3SBarry Smith PetscErrorCode DMPlexGetMaxSizes(DM dm, PeOp PetscInt *maxConeSize, PeOp PetscInt *maxSupportSize) 4300d71ae5a4SJacob Faibussowitsch { 4301552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4302552f7358SJed Brown 4303552f7358SJed Brown PetscFunctionBegin; 4304552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43051baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 43061baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 43073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4308552f7358SJed Brown } 4309552f7358SJed Brown 4310d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4311d71ae5a4SJacob Faibussowitsch { 4312552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 43136302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4314552f7358SJed Brown 4315552f7358SJed Brown PetscFunctionBegin; 4316552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 43179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 43189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 43199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 43209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 43216302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 43226302a7fbSVaclav Hapla if (maxSupportSize) { 43239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 43249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 43259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4326552f7358SJed Brown } 43273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4328552f7358SJed Brown } 4329552f7358SJed Brown 4330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4331d71ae5a4SJacob Faibussowitsch { 4332552f7358SJed Brown PetscFunctionBegin; 43339566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4334dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4335ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4336736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 433795602cf2SAlexis Marboeuf PetscSF sfNatural; 4338f94b4a02SBlaise Bourdin 43393dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 43409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 434195602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4342c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4343f94b4a02SBlaise Bourdin } 43443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4345552f7358SJed Brown } 4346552f7358SJed Brown 4347d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4348d71ae5a4SJacob Faibussowitsch { 43493dcd263cSBlaise Bourdin PetscInt i = 0; 43502adcc780SMatthew G. Knepley 43512adcc780SMatthew G. Knepley PetscFunctionBegin; 43529566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 43539566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4354c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 43553dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 43563dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 435795602cf2SAlexis Marboeuf PetscSF sfNatural; 43583dcd263cSBlaise Bourdin 43593dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 43609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4361c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 436295602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4363c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 43643dcd263cSBlaise Bourdin break; 43653dcd263cSBlaise Bourdin } 43663dcd263cSBlaise Bourdin } 43673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43682adcc780SMatthew G. Knepley } 43692adcc780SMatthew G. Knepley 4370552f7358SJed Brown /*@ 4371eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4372552f7358SJed Brown 4373a1cb98faSBarry Smith Not Collective 4374552f7358SJed Brown 4375552f7358SJed Brown Input Parameter: 437660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4377552f7358SJed Brown 4378552f7358SJed Brown Level: beginner 4379552f7358SJed Brown 4380a1cb98faSBarry Smith Note: 4381a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4382a1cb98faSBarry Smith 43831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4384552f7358SJed Brown @*/ 4385d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4386d71ae5a4SJacob Faibussowitsch { 4387552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4388552f7358SJed Brown PetscInt *offsets; 4389552f7358SJed Brown PetscInt supportSize; 4390552f7358SJed Brown PetscInt pStart, pEnd, p; 4391552f7358SJed Brown 4392552f7358SJed Brown PetscFunctionBegin; 4393552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 439428b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 43959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4396552f7358SJed Brown /* Calculate support sizes */ 43979566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4398552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4399552f7358SJed Brown PetscInt dof, off, c; 4400552f7358SJed Brown 44019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 44029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 440348a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4404552f7358SJed Brown } 44059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4406552f7358SJed Brown /* Calculate supports */ 44079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 44089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 44099566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4410552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4411552f7358SJed Brown PetscInt dof, off, c; 4412552f7358SJed Brown 44139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 44149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4415552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4416552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4417552f7358SJed Brown PetscInt offS; 4418552f7358SJed Brown 44199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 44200d644c17SKarl Rupp 4421552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4422552f7358SJed Brown ++offsets[q]; 4423552f7358SJed Brown } 4424552f7358SJed Brown } 44259566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 44269566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 44273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4428552f7358SJed Brown } 4429552f7358SJed Brown 4430d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4431d71ae5a4SJacob Faibussowitsch { 4432277ea44aSLisandro Dalcin IS stratumIS; 4433277ea44aSLisandro Dalcin 4434277ea44aSLisandro Dalcin PetscFunctionBegin; 44353ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 443676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4437277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4438277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 44399566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4440277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 44419566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 44429371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 44439371c9d4SSatish Balay overlap = PETSC_TRUE; 44449371c9d4SSatish Balay break; 44459371c9d4SSatish Balay } 4446277ea44aSLisandro Dalcin } 444763a3b9bcSJacob 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); 4448277ea44aSLisandro Dalcin } 44499566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 44509566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 44519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 44523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4453277ea44aSLisandro Dalcin } 4454277ea44aSLisandro Dalcin 4455e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4456e91fa0a1SMatthew G. Knepley { 4457e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4458e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 44591690c2aeSBarry Smith PetscInt dmin = PETSC_INT_MAX, dmax = PETSC_INT_MIN; 4460e91fa0a1SMatthew G. Knepley 4461e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4462e91fa0a1SMatthew G. Knepley { 4463e91fa0a1SMatthew G. Knepley DMLabel label2; 4464e91fa0a1SMatthew G. Knepley 4465e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4466e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4467e91fa0a1SMatthew G. Knepley } 4468e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4469e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4470e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4471e91fa0a1SMatthew G. Knepley 4472e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4473e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4474e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4475e91fa0a1SMatthew G. Knepley } 4476e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4477e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 44781690c2aeSBarry Smith pMin[d] = PETSC_INT_MAX; 44791690c2aeSBarry Smith pMax[d] = PETSC_INT_MIN; 4480e91fa0a1SMatthew G. Knepley } 4481e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4482e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4483e91fa0a1SMatthew G. Knepley PetscInt d; 4484e91fa0a1SMatthew G. Knepley 4485e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4486e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4487e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4488e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4489e91fa0a1SMatthew G. Knepley } 4490e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4491e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4492e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4493e91fa0a1SMatthew G. Knepley } 4494e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4495e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4496e91fa0a1SMatthew G. Knepley } 4497e91fa0a1SMatthew G. Knepley 4498e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4499e91fa0a1SMatthew G. Knepley { 4500e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4501e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4502e91fa0a1SMatthew G. Knepley 4503e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4504e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4505e91fa0a1SMatthew G. Knepley { 4506e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 45071690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45081690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4509e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4510e91fa0a1SMatthew G. Knepley 4511e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4512e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4513e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4514e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4515e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4516e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4517e91fa0a1SMatthew G. Knepley ++numRoots; 4518e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4519e91fa0a1SMatthew G. Knepley ++numLeaves; 4520e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4521e91fa0a1SMatthew G. Knepley /* Isolated points */ 4522e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4523e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4524e91fa0a1SMatthew G. Knepley } 4525e91fa0a1SMatthew G. Knepley } 4526e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4527e91fa0a1SMatthew G. Knepley } 4528e91fa0a1SMatthew G. Knepley 4529e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 45301690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45311690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4532e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4533e91fa0a1SMatthew G. Knepley 4534e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4535e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4536e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4537e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4538e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4539e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4540e91fa0a1SMatthew G. Knepley } 4541e91fa0a1SMatthew G. Knepley } 4542e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4543e91fa0a1SMatthew G. Knepley } else { 4544e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4545e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4546e91fa0a1SMatthew G. Knepley 4547e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4548e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 45491690c2aeSBarry Smith PetscInt sMin = PETSC_INT_MAX; 45501690c2aeSBarry Smith PetscInt sMax = PETSC_INT_MIN; 4551e91fa0a1SMatthew G. Knepley 4552e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4553e91fa0a1SMatthew G. Knepley const PetscInt *support; 4554e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4555e91fa0a1SMatthew G. Knepley 4556e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4557e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4558e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4559e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4560e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4561e91fa0a1SMatthew G. Knepley } 4562e91fa0a1SMatthew G. Knepley } 4563e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4564e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4565e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4566e91fa0a1SMatthew G. Knepley } 4567e91fa0a1SMatthew G. Knepley } 4568e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4569e91fa0a1SMatthew G. Knepley } 4570e91fa0a1SMatthew G. Knepley 4571552f7358SJed Brown /*@ 4572a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4573552f7358SJed Brown 457420f4b53cSBarry Smith Collective 4575552f7358SJed Brown 4576552f7358SJed Brown Input Parameter: 457760225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4578552f7358SJed Brown 4579a1cb98faSBarry Smith Level: beginner 4580552f7358SJed Brown 4581552f7358SJed Brown Notes: 4582a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4583a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4584a4e35b19SJacob Faibussowitsch 4585a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4586a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4587a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4588b1bb481bSMatthew 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 4589a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4590a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4591a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4592552f7358SJed Brown 4593b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4594b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4595b1bb481bSMatthew 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 4596b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4597a1cb98faSBarry Smith .vb 4598a1cb98faSBarry Smith cone(c0) = {e0, v2} 4599a1cb98faSBarry Smith cone(e0) = {v0, v1} 4600a1cb98faSBarry Smith .ve 4601a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4602a1cb98faSBarry Smith .vb 4603a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4604a1cb98faSBarry Smith depth 1 = {e0, c0} 4605a1cb98faSBarry Smith .ve 4606b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4607b1bb481bSMatthew Knepley 4608a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4609552f7358SJed Brown 46101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4611552f7358SJed Brown @*/ 4612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4613d71ae5a4SJacob Faibussowitsch { 4614df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4615aa50250dSMatthew G. Knepley DMLabel label; 4616e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4617552f7358SJed Brown 4618552f7358SJed Brown PetscFunctionBegin; 4619552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4621277ea44aSLisandro Dalcin 4622e91fa0a1SMatthew G. Knepley // Create depth label 4623d28dd301SMatthew G. Knepley PetscCall(DMRemoveLabel(dm, "depth", NULL)); 46249566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 46259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4626277ea44aSLisandro Dalcin 4627e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4628e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4629e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4630552f7358SJed Brown 4631bf4602e4SToby Isaac { /* just in case there is an empty process */ 4632bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4633bf4602e4SToby Isaac 46349566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4635462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 463648a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4637bf4602e4SToby Isaac } 46389566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 46399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 46403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4641552f7358SJed Brown } 4642552f7358SJed Brown 4643d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4644d71ae5a4SJacob Faibussowitsch { 4645412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4646412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 46475e2c5519SMatthew G. Knepley PetscBool preferTensor; 4648ba2698f1SMatthew G. Knepley 4649412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 46509566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 46519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 46529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 46535e2c5519SMatthew G. Knepley PetscCall(DMPlexGetInterpolatePreferTensor(dm, &preferTensor)); 4654ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4655ba2698f1SMatthew G. Knepley if (depth <= 1) { 4656ba2698f1SMatthew G. Knepley switch (pdepth) { 4657d71ae5a4SJacob Faibussowitsch case 0: 4658d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4659d71ae5a4SJacob Faibussowitsch break; 4660ba2698f1SMatthew G. Knepley case 1: 4661ba2698f1SMatthew G. Knepley switch (coneSize) { 4662d71ae5a4SJacob Faibussowitsch case 2: 4663d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4664d71ae5a4SJacob Faibussowitsch break; 4665d71ae5a4SJacob Faibussowitsch case 3: 4666d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4667d71ae5a4SJacob Faibussowitsch break; 4668ba2698f1SMatthew G. Knepley case 4: 4669ba2698f1SMatthew G. Knepley switch (dim) { 4670d71ae5a4SJacob Faibussowitsch case 2: 4671d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4672d71ae5a4SJacob Faibussowitsch break; 4673d71ae5a4SJacob Faibussowitsch case 3: 4674d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4675d71ae5a4SJacob Faibussowitsch break; 4676d71ae5a4SJacob Faibussowitsch default: 4677d71ae5a4SJacob Faibussowitsch break; 4678ba2698f1SMatthew G. Knepley } 4679ba2698f1SMatthew G. Knepley break; 4680d71ae5a4SJacob Faibussowitsch case 5: 4681d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4682d71ae5a4SJacob Faibussowitsch break; 4683d71ae5a4SJacob Faibussowitsch case 6: 46845e2c5519SMatthew G. Knepley ct = preferTensor ? DM_POLYTOPE_TRI_PRISM_TENSOR : DM_POLYTOPE_TRI_PRISM; 4685d71ae5a4SJacob Faibussowitsch break; 4686d71ae5a4SJacob Faibussowitsch case 8: 4687d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4688d71ae5a4SJacob Faibussowitsch break; 4689d71ae5a4SJacob Faibussowitsch default: 4690d71ae5a4SJacob Faibussowitsch break; 4691ba2698f1SMatthew G. Knepley } 4692ba2698f1SMatthew G. Knepley } 4693ba2698f1SMatthew G. Knepley } else { 4694ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4695ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4696ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4697ba2698f1SMatthew G. Knepley switch (dim) { 4698ba2698f1SMatthew G. Knepley case 1: 4699ba2698f1SMatthew G. Knepley switch (coneSize) { 4700d71ae5a4SJacob Faibussowitsch case 2: 4701d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4702d71ae5a4SJacob Faibussowitsch break; 4703d71ae5a4SJacob Faibussowitsch default: 4704d71ae5a4SJacob Faibussowitsch break; 4705ba2698f1SMatthew G. Knepley } 4706ba2698f1SMatthew G. Knepley break; 4707ba2698f1SMatthew G. Knepley case 2: 4708ba2698f1SMatthew G. Knepley switch (coneSize) { 4709d71ae5a4SJacob Faibussowitsch case 3: 4710d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4711d71ae5a4SJacob Faibussowitsch break; 4712d71ae5a4SJacob Faibussowitsch case 4: 4713d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4714d71ae5a4SJacob Faibussowitsch break; 4715d71ae5a4SJacob Faibussowitsch default: 4716d71ae5a4SJacob Faibussowitsch break; 4717ba2698f1SMatthew G. Knepley } 4718ba2698f1SMatthew G. Knepley break; 4719ba2698f1SMatthew G. Knepley case 3: 4720ba2698f1SMatthew G. Knepley switch (coneSize) { 4721d71ae5a4SJacob Faibussowitsch case 4: 4722d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4723d71ae5a4SJacob Faibussowitsch break; 47249371c9d4SSatish Balay case 5: { 4725da9060c4SMatthew G. Knepley const PetscInt *cone; 4726da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4727da9060c4SMatthew G. Knepley 47289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 47299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4730da9060c4SMatthew G. Knepley switch (faceConeSize) { 4731d71ae5a4SJacob Faibussowitsch case 3: 47325e2c5519SMatthew G. Knepley ct = preferTensor ? DM_POLYTOPE_TRI_PRISM_TENSOR : DM_POLYTOPE_TRI_PRISM; 4733d71ae5a4SJacob Faibussowitsch break; 4734d71ae5a4SJacob Faibussowitsch case 4: 4735d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4736d71ae5a4SJacob Faibussowitsch break; 4737da9060c4SMatthew G. Knepley } 47389371c9d4SSatish Balay } break; 4739d71ae5a4SJacob Faibussowitsch case 6: 4740d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4741d71ae5a4SJacob Faibussowitsch break; 4742d71ae5a4SJacob Faibussowitsch default: 4743d71ae5a4SJacob Faibussowitsch break; 4744ba2698f1SMatthew G. Knepley } 4745ba2698f1SMatthew G. Knepley break; 4746d71ae5a4SJacob Faibussowitsch default: 4747d71ae5a4SJacob Faibussowitsch break; 4748ba2698f1SMatthew G. Knepley } 4749ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4750ba2698f1SMatthew G. Knepley switch (coneSize) { 4751d71ae5a4SJacob Faibussowitsch case 2: 4752d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4753d71ae5a4SJacob Faibussowitsch break; 4754d71ae5a4SJacob Faibussowitsch case 3: 4755d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4756d71ae5a4SJacob Faibussowitsch break; 4757d71ae5a4SJacob Faibussowitsch case 4: 4758d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4759d71ae5a4SJacob Faibussowitsch break; 4760d71ae5a4SJacob Faibussowitsch default: 4761d71ae5a4SJacob Faibussowitsch break; 4762ba2698f1SMatthew G. Knepley } 4763ba2698f1SMatthew G. Knepley } 4764ba2698f1SMatthew G. Knepley } 4765412e9a14SMatthew G. Knepley *pt = ct; 47663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4767ba2698f1SMatthew G. Knepley } 4768412e9a14SMatthew G. Knepley 4769412e9a14SMatthew G. Knepley /*@ 4770412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4771412e9a14SMatthew G. Knepley 477220f4b53cSBarry Smith Collective 4773412e9a14SMatthew G. Knepley 4774412e9a14SMatthew G. Knepley Input Parameter: 477560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4776412e9a14SMatthew G. Knepley 4777412e9a14SMatthew G. Knepley Level: developer 4778412e9a14SMatthew G. Knepley 4779a1cb98faSBarry Smith Note: 4780a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4781a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4782a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4783412e9a14SMatthew G. Knepley 4784a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4785a1cb98faSBarry Smith 47861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4787412e9a14SMatthew G. Knepley @*/ 4788d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4789d71ae5a4SJacob Faibussowitsch { 4790412e9a14SMatthew G. Knepley DM_Plex *mesh; 4791412e9a14SMatthew G. Knepley DMLabel ctLabel; 4792412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4793412e9a14SMatthew G. Knepley 4794412e9a14SMatthew G. Knepley PetscFunctionBegin; 4795412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4796412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 47979566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 47989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 47999566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 480021027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 480121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4802412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4803327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4804412e9a14SMatthew G. Knepley PetscInt pdepth; 4805412e9a14SMatthew G. Knepley 48069566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 48079566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4808841fc1b7SMatthew 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]); 48099566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 48106497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 4811412e9a14SMatthew G. Knepley } 48129566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 48139566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 48143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4815ba2698f1SMatthew G. Knepley } 4816ba2698f1SMatthew G. Knepley 4817552f7358SJed Brown /*@C 4818552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4819552f7358SJed Brown 4820552f7358SJed Brown Not Collective 4821552f7358SJed Brown 4822552f7358SJed Brown Input Parameters: 4823a1cb98faSBarry Smith + dm - The `DMPLEX` object 4824552f7358SJed Brown . numPoints - The number of input points for the join 4825552f7358SJed Brown - points - The input points 4826552f7358SJed Brown 4827552f7358SJed Brown Output Parameters: 4828552f7358SJed Brown + numCoveredPoints - The number of points in the join 4829552f7358SJed Brown - coveredPoints - The points in the join 4830552f7358SJed Brown 4831552f7358SJed Brown Level: intermediate 4832552f7358SJed Brown 4833a1cb98faSBarry Smith Note: 4834a1cb98faSBarry Smith Currently, this is restricted to a single level join 4835552f7358SJed Brown 483660225df5SJacob Faibussowitsch Fortran Notes: 48372c9a7b26SBarry Smith `converedPoints` must be declared with 48382c9a7b26SBarry Smith .vb 48392c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 48402c9a7b26SBarry Smith .ve 48412c9a7b26SBarry Smith 48421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4843552f7358SJed Brown @*/ 48445d83a8b1SBarry Smith PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4845d71ae5a4SJacob Faibussowitsch { 4846552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4847552f7358SJed Brown PetscInt *join[2]; 4848552f7358SJed Brown PetscInt joinSize, i = 0; 4849552f7358SJed Brown PetscInt dof, off, p, c, m; 48506302a7fbSVaclav Hapla PetscInt maxSupportSize; 4851552f7358SJed Brown 4852552f7358SJed Brown PetscFunctionBegin; 4853552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48544f572ea9SToby Isaac PetscAssertPointer(points, 3); 48554f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 48564f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 48576302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 48586302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 48596302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4860552f7358SJed Brown /* Copy in support of first point */ 48619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 48629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4863ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4864552f7358SJed Brown /* Check each successive support */ 4865552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4866552f7358SJed Brown PetscInt newJoinSize = 0; 4867552f7358SJed Brown 48689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 48699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4870552f7358SJed Brown for (c = 0; c < dof; ++c) { 4871552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4872552f7358SJed Brown 4873552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4874552f7358SJed Brown if (point == join[i][m]) { 4875552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4876552f7358SJed Brown break; 4877552f7358SJed Brown } 4878552f7358SJed Brown } 4879552f7358SJed Brown } 4880552f7358SJed Brown joinSize = newJoinSize; 4881552f7358SJed Brown i = 1 - i; 4882552f7358SJed Brown } 4883552f7358SJed Brown *numCoveredPoints = joinSize; 4884552f7358SJed Brown *coveredPoints = join[i]; 48856302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 48863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4887552f7358SJed Brown } 4888552f7358SJed Brown 4889552f7358SJed Brown /*@C 48902c9a7b26SBarry Smith DMPlexRestoreJoin - Restore an array for the join of the set of points obtained with `DMPlexGetJoin()` 4891552f7358SJed Brown 4892552f7358SJed Brown Not Collective 4893552f7358SJed Brown 4894552f7358SJed Brown Input Parameters: 4895a1cb98faSBarry Smith + dm - The `DMPLEX` object 4896552f7358SJed Brown . numPoints - The number of input points for the join 4897552f7358SJed Brown - points - The input points 4898552f7358SJed Brown 4899552f7358SJed Brown Output Parameters: 4900552f7358SJed Brown + numCoveredPoints - The number of points in the join 4901552f7358SJed Brown - coveredPoints - The points in the join 4902552f7358SJed Brown 4903552f7358SJed Brown Level: intermediate 4904552f7358SJed Brown 490560225df5SJacob Faibussowitsch Fortran Notes: 4906feaf08eaSBarry Smith `converedPoints` must be declared with 4907feaf08eaSBarry Smith .vb 4908feaf08eaSBarry Smith PetscInt, pointer :: coveredPoints(:) 4909feaf08eaSBarry Smith .ve 4910feaf08eaSBarry Smith 4911feaf08eaSBarry Smith Pass `PETSC_NULL_INTEGER` for `numCoveredPoints` if it is not needed 4912a1cb98faSBarry Smith 49131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4914552f7358SJed Brown @*/ 49152c9a7b26SBarry Smith PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4916d71ae5a4SJacob Faibussowitsch { 4917552f7358SJed Brown PetscFunctionBegin; 4918552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49194f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49204f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49214f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4923d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4925552f7358SJed Brown } 4926552f7358SJed Brown 4927552f7358SJed Brown /*@C 4928552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4929552f7358SJed Brown 4930552f7358SJed Brown Not Collective 4931552f7358SJed Brown 4932552f7358SJed Brown Input Parameters: 4933a1cb98faSBarry Smith + dm - The `DMPLEX` object 4934552f7358SJed Brown . numPoints - The number of input points for the join 49352c9a7b26SBarry Smith - points - The input points, its length is `numPoints` 4936552f7358SJed Brown 4937552f7358SJed Brown Output Parameters: 4938552f7358SJed Brown + numCoveredPoints - The number of points in the join 49392c9a7b26SBarry Smith - coveredPoints - The points in the join, its length is `numCoveredPoints` 4940552f7358SJed Brown 4941552f7358SJed Brown Level: intermediate 4942552f7358SJed Brown 494360225df5SJacob Faibussowitsch Fortran Notes: 49442c9a7b26SBarry Smith .vb 49452c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 49462c9a7b26SBarry Smith .ve 49472c9a7b26SBarry Smith 49481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4949552f7358SJed Brown @*/ 49505d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4951d71ae5a4SJacob Faibussowitsch { 4952552f7358SJed Brown PetscInt *offsets, **closures; 4953552f7358SJed Brown PetscInt *join[2]; 4954552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 495524c766afSToby Isaac PetscInt p, d, c, m, ms; 4956552f7358SJed Brown 4957552f7358SJed Brown PetscFunctionBegin; 4958552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49594f572ea9SToby Isaac PetscAssertPointer(points, 3); 49604f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49614f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4962552f7358SJed Brown 49639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 49649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 49659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 49666302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 496724c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 49689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 49699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4970552f7358SJed Brown 4971552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4972552f7358SJed Brown PetscInt closureSize; 4973552f7358SJed Brown 49749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 49750d644c17SKarl Rupp 4976552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4977552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4978552f7358SJed Brown PetscInt pStart, pEnd, i; 4979552f7358SJed Brown 49809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4981552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4982552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4983552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4984552f7358SJed Brown break; 4985552f7358SJed Brown } 4986552f7358SJed Brown } 4987552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4988552f7358SJed Brown } 498963a3b9bcSJacob 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); 4990552f7358SJed Brown } 4991552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4992552f7358SJed Brown PetscInt dof; 4993552f7358SJed Brown 4994552f7358SJed Brown /* Copy in support of first point */ 4995552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4996ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4997552f7358SJed Brown /* Check each successive cone */ 4998552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4999552f7358SJed Brown PetscInt newJoinSize = 0; 5000552f7358SJed Brown 5001552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 5002552f7358SJed Brown for (c = 0; c < dof; ++c) { 5003552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 5004552f7358SJed Brown 5005552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 5006552f7358SJed Brown if (point == join[i][m]) { 5007552f7358SJed Brown join[1 - i][newJoinSize++] = point; 5008552f7358SJed Brown break; 5009552f7358SJed Brown } 5010552f7358SJed Brown } 5011552f7358SJed Brown } 5012552f7358SJed Brown joinSize = newJoinSize; 5013552f7358SJed Brown i = 1 - i; 5014552f7358SJed Brown } 5015552f7358SJed Brown if (joinSize) break; 5016552f7358SJed Brown } 5017552f7358SJed Brown *numCoveredPoints = joinSize; 5018552f7358SJed Brown *coveredPoints = join[i]; 501948a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 50209566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 50226302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 50233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5024552f7358SJed Brown } 5025552f7358SJed Brown 5026552f7358SJed Brown /*@C 5027552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 5028552f7358SJed Brown 5029552f7358SJed Brown Not Collective 5030552f7358SJed Brown 5031552f7358SJed Brown Input Parameters: 5032a1cb98faSBarry Smith + dm - The `DMPLEX` object 5033552f7358SJed Brown . numPoints - The number of input points for the meet 50342c9a7b26SBarry Smith - points - The input points, of length `numPoints` 5035552f7358SJed Brown 5036552f7358SJed Brown Output Parameters: 503760225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 50382c9a7b26SBarry Smith - coveringPoints - The points in the meet, of length `numCoveringPoints` 5039552f7358SJed Brown 5040552f7358SJed Brown Level: intermediate 5041552f7358SJed Brown 5042a1cb98faSBarry Smith Note: 5043a1cb98faSBarry Smith Currently, this is restricted to a single level meet 5044552f7358SJed Brown 5045feaf08eaSBarry Smith Fortran Note: 50462c9a7b26SBarry Smith `coveringPoints` must be declared with 50472c9a7b26SBarry Smith .vb 50482c9a7b26SBarry Smith PetscInt, pointer :: coveringPoints(:) 50492c9a7b26SBarry Smith .ve 50502c9a7b26SBarry Smith 50511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 5052552f7358SJed Brown @*/ 50535d83a8b1SBarry Smith PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt *coveringPoints[]) 5054d71ae5a4SJacob Faibussowitsch { 5055552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5056552f7358SJed Brown PetscInt *meet[2]; 5057552f7358SJed Brown PetscInt meetSize, i = 0; 5058552f7358SJed Brown PetscInt dof, off, p, c, m; 50596302a7fbSVaclav Hapla PetscInt maxConeSize; 5060552f7358SJed Brown 5061552f7358SJed Brown PetscFunctionBegin; 5062552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50634f572ea9SToby Isaac PetscAssertPointer(points, 3); 50644f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 50654f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 50666302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 50676302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 50686302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 5069552f7358SJed Brown /* Copy in cone of first point */ 50709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 50719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 5072ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 5073552f7358SJed Brown /* Check each successive cone */ 5074552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 5075552f7358SJed Brown PetscInt newMeetSize = 0; 5076552f7358SJed Brown 50779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 50789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 5079552f7358SJed Brown for (c = 0; c < dof; ++c) { 5080552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 5081552f7358SJed Brown 5082552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5083552f7358SJed Brown if (point == meet[i][m]) { 5084552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5085552f7358SJed Brown break; 5086552f7358SJed Brown } 5087552f7358SJed Brown } 5088552f7358SJed Brown } 5089552f7358SJed Brown meetSize = newMeetSize; 5090552f7358SJed Brown i = 1 - i; 5091552f7358SJed Brown } 5092552f7358SJed Brown *numCoveringPoints = meetSize; 5093552f7358SJed Brown *coveringPoints = meet[i]; 50946302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 50953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5096552f7358SJed Brown } 5097552f7358SJed Brown 5098552f7358SJed Brown /*@C 50992c9a7b26SBarry Smith DMPlexRestoreMeet - Restore an array for the meet of the set of points obtained with `DMPlexGetMeet()` 5100552f7358SJed Brown 5101552f7358SJed Brown Not Collective 5102552f7358SJed Brown 5103552f7358SJed Brown Input Parameters: 5104a1cb98faSBarry Smith + dm - The `DMPLEX` object 5105552f7358SJed Brown . numPoints - The number of input points for the meet 5106552f7358SJed Brown - points - The input points 5107552f7358SJed Brown 5108552f7358SJed Brown Output Parameters: 5109552f7358SJed Brown + numCoveredPoints - The number of points in the meet 5110552f7358SJed Brown - coveredPoints - The points in the meet 5111552f7358SJed Brown 5112552f7358SJed Brown Level: intermediate 5113552f7358SJed Brown 51141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 5115552f7358SJed Brown @*/ 51165d83a8b1SBarry Smith PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5117d71ae5a4SJacob Faibussowitsch { 5118552f7358SJed Brown PetscFunctionBegin; 5119552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51204f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 51214f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 51224f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 51239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 5124d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 51253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5126552f7358SJed Brown } 5127552f7358SJed Brown 5128552f7358SJed Brown /*@C 5129552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 5130552f7358SJed Brown 5131552f7358SJed Brown Not Collective 5132552f7358SJed Brown 5133552f7358SJed Brown Input Parameters: 5134a1cb98faSBarry Smith + dm - The `DMPLEX` object 5135552f7358SJed Brown . numPoints - The number of input points for the meet 51362c9a7b26SBarry Smith - points - The input points, of length `numPoints` 5137552f7358SJed Brown 5138552f7358SJed Brown Output Parameters: 5139552f7358SJed Brown + numCoveredPoints - The number of points in the meet 51402c9a7b26SBarry Smith - coveredPoints - The points in the meet, of length `numCoveredPoints` 5141552f7358SJed Brown 5142552f7358SJed Brown Level: intermediate 5143552f7358SJed Brown 514460225df5SJacob Faibussowitsch Fortran Notes: 5145feaf08eaSBarry Smith `coveredPoints` must be declared with 51462c9a7b26SBarry Smith .vb 51472c9a7b26SBarry Smith PetscInt, pointer :: coveredPoints(:) 51482c9a7b26SBarry Smith .ve 51492c9a7b26SBarry Smith 51501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 5151552f7358SJed Brown @*/ 51525d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5153d71ae5a4SJacob Faibussowitsch { 5154552f7358SJed Brown PetscInt *offsets, **closures; 5155552f7358SJed Brown PetscInt *meet[2]; 5156552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 515724c766afSToby Isaac PetscInt p, h, c, m, mc; 5158552f7358SJed Brown 5159552f7358SJed Brown PetscFunctionBegin; 5160552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51614f572ea9SToby Isaac PetscAssertPointer(points, 3); 51624f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 51634f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 5164552f7358SJed Brown 51659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 51669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 51679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 51686302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 516924c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 51709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 51719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 5172552f7358SJed Brown 5173552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 5174552f7358SJed Brown PetscInt closureSize; 5175552f7358SJed Brown 51769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 51770d644c17SKarl Rupp 5178552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 5179552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5180552f7358SJed Brown PetscInt pStart, pEnd, i; 5181552f7358SJed Brown 51829566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 5183552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 5184552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 5185552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 5186552f7358SJed Brown break; 5187552f7358SJed Brown } 5188552f7358SJed Brown } 5189552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 5190552f7358SJed Brown } 519163a3b9bcSJacob 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); 5192552f7358SJed Brown } 5193552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5194552f7358SJed Brown PetscInt dof; 5195552f7358SJed Brown 5196552f7358SJed Brown /* Copy in cone of first point */ 5197552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5198ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5199552f7358SJed Brown /* Check each successive cone */ 5200552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5201552f7358SJed Brown PetscInt newMeetSize = 0; 5202552f7358SJed Brown 5203552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5204552f7358SJed Brown for (c = 0; c < dof; ++c) { 5205552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5206552f7358SJed Brown 5207552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5208552f7358SJed Brown if (point == meet[i][m]) { 5209552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5210552f7358SJed Brown break; 5211552f7358SJed Brown } 5212552f7358SJed Brown } 5213552f7358SJed Brown } 5214552f7358SJed Brown meetSize = newMeetSize; 5215552f7358SJed Brown i = 1 - i; 5216552f7358SJed Brown } 5217552f7358SJed Brown if (meetSize) break; 5218552f7358SJed Brown } 5219552f7358SJed Brown *numCoveredPoints = meetSize; 5220552f7358SJed Brown *coveredPoints = meet[i]; 522148a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 52229566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 52239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 52246302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 52253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5226552f7358SJed Brown } 5227552f7358SJed Brown 5228cc4c1da9SBarry Smith /*@ 5229a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 52304e3744c5SMatthew G. Knepley 52314e3744c5SMatthew G. Knepley Not Collective 52324e3744c5SMatthew G. Knepley 52334e3744c5SMatthew G. Knepley Input Parameters: 5234a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5235a1cb98faSBarry Smith - dmB - A `DMPLEX` object 52364e3744c5SMatthew G. Knepley 52372fe279fdSBarry Smith Output Parameter: 5238a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 52394e3744c5SMatthew G. Knepley 52404e3744c5SMatthew G. Knepley Level: intermediate 52414e3744c5SMatthew G. Knepley 5242a1cb98faSBarry Smith Note: 52433c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 52444e3744c5SMatthew G. Knepley 52451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 52464e3744c5SMatthew G. Knepley @*/ 5247d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5248d71ae5a4SJacob Faibussowitsch { 52494e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 52504e3744c5SMatthew G. Knepley 52514e3744c5SMatthew G. Knepley PetscFunctionBegin; 52524e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 52534e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 52544f572ea9SToby Isaac PetscAssertPointer(equal, 3); 52554e3744c5SMatthew G. Knepley 52564e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 52579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 52589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 52593ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 52609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 52619566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 52623ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 52634e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 52644e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 52654e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 52664e3744c5SMatthew G. Knepley 52679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 52689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 52699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 52709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 52719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 52729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 52733ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 52744e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 52753ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52763ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52774e3744c5SMatthew G. Knepley } 52789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 52809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 52819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 52823ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 52834e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 52843ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 52854e3744c5SMatthew G. Knepley } 52864e3744c5SMatthew G. Knepley } 52874e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 52883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52894e3744c5SMatthew G. Knepley } 52904e3744c5SMatthew G. Knepley 5291cc4c1da9SBarry Smith /*@ 52927cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 52937cd05799SMatthew G. Knepley 52947cd05799SMatthew G. Knepley Not Collective 52957cd05799SMatthew G. Knepley 52967cd05799SMatthew G. Knepley Input Parameters: 5297a1cb98faSBarry Smith + dm - The `DMPLEX` 52987cd05799SMatthew G. Knepley . cellDim - The cell dimension 52997cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 53007cd05799SMatthew G. Knepley 53012fe279fdSBarry Smith Output Parameter: 53027cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 53037cd05799SMatthew G. Knepley 53047cd05799SMatthew G. Knepley Level: developer 53057cd05799SMatthew G. Knepley 5306a1cb98faSBarry Smith Note: 53077cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 53087cd05799SMatthew G. Knepley 53091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 53107cd05799SMatthew G. Knepley @*/ 5311d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5312d71ae5a4SJacob Faibussowitsch { 531382f516ccSBarry Smith MPI_Comm comm; 5314552f7358SJed Brown 5315552f7358SJed Brown PetscFunctionBegin; 53169566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 53174f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5318552f7358SJed Brown switch (cellDim) { 5319d71ae5a4SJacob Faibussowitsch case 0: 5320d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5321d71ae5a4SJacob Faibussowitsch break; 5322d71ae5a4SJacob Faibussowitsch case 1: 5323d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5324d71ae5a4SJacob Faibussowitsch break; 5325552f7358SJed Brown case 2: 5326552f7358SJed Brown switch (numCorners) { 532719436ca2SJed Brown case 3: /* triangle */ 532819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5329552f7358SJed Brown break; 533019436ca2SJed Brown case 4: /* quadrilateral */ 533119436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5332552f7358SJed Brown break; 533319436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 533419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5335552f7358SJed Brown break; 533619436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 533719436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5338552f7358SJed Brown break; 5339d71ae5a4SJacob Faibussowitsch default: 5340d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5341552f7358SJed Brown } 5342552f7358SJed Brown break; 5343552f7358SJed Brown case 3: 5344552f7358SJed Brown switch (numCorners) { 534519436ca2SJed Brown case 4: /* tetradehdron */ 534619436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5347552f7358SJed Brown break; 534819436ca2SJed Brown case 6: /* tet cohesive cells */ 534919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5350552f7358SJed Brown break; 535119436ca2SJed Brown case 8: /* hexahedron */ 535219436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5353552f7358SJed Brown break; 535419436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 535519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5356552f7358SJed Brown break; 535719436ca2SJed Brown case 10: /* quadratic tetrahedron */ 535819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5359552f7358SJed Brown break; 536019436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 536119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5362552f7358SJed Brown break; 536319436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 536419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5365552f7358SJed Brown break; 536619436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 536719436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5368552f7358SJed Brown break; 5369d71ae5a4SJacob Faibussowitsch default: 5370d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5371552f7358SJed Brown } 5372552f7358SJed Brown break; 5373d71ae5a4SJacob Faibussowitsch default: 5374d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5375552f7358SJed Brown } 53763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5377552f7358SJed Brown } 5378552f7358SJed Brown 5379552f7358SJed Brown /*@ 5380a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5381552f7358SJed Brown 5382552f7358SJed Brown Not Collective 5383552f7358SJed Brown 5384aa50250dSMatthew G. Knepley Input Parameter: 5385a1cb98faSBarry Smith . dm - The `DMPLEX` object 5386552f7358SJed Brown 5387aa50250dSMatthew G. Knepley Output Parameter: 5388a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5389552f7358SJed Brown 5390552f7358SJed Brown Level: developer 5391552f7358SJed Brown 53921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5393aa50250dSMatthew G. Knepley @*/ 5394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5395d71ae5a4SJacob Faibussowitsch { 5396aa50250dSMatthew G. Knepley PetscFunctionBegin; 5397aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53984f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5399c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 54003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5401aa50250dSMatthew G. Knepley } 5402aa50250dSMatthew G. Knepley 5403aa50250dSMatthew G. Knepley /*@ 5404aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5405aa50250dSMatthew G. Knepley 5406aa50250dSMatthew G. Knepley Not Collective 5407aa50250dSMatthew G. Knepley 5408aa50250dSMatthew G. Knepley Input Parameter: 5409a1cb98faSBarry Smith . dm - The `DMPLEX` object 5410aa50250dSMatthew G. Knepley 5411aa50250dSMatthew G. Knepley Output Parameter: 5412aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5413aa50250dSMatthew G. Knepley 5414aa50250dSMatthew G. Knepley Level: developer 5415552f7358SJed Brown 5416b1bb481bSMatthew Knepley Notes: 5417a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5418a1cb98faSBarry Smith 5419a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5420a1cb98faSBarry Smith 5421dc287ab2SVaclav Hapla An empty mesh gives -1. 5422b1bb481bSMatthew Knepley 54231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5424552f7358SJed Brown @*/ 5425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5426d71ae5a4SJacob Faibussowitsch { 54279f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5428aa50250dSMatthew G. Knepley DMLabel label; 5429452349dbSMatthew G. Knepley PetscInt d = -1; 5430552f7358SJed Brown 5431552f7358SJed Brown PetscFunctionBegin; 5432552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54334f572ea9SToby Isaac PetscAssertPointer(depth, 2); 54349f4ada15SMatthew G. Knepley if (mesh->tr) { 54359f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 54369f4ada15SMatthew G. Knepley } else { 54379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 5438452349dbSMatthew G. Knepley // Allow missing depths 5439452349dbSMatthew G. Knepley if (label) PetscCall(DMLabelGetValueBounds(label, NULL, &d)); 5440452349dbSMatthew G. Knepley *depth = d; 54419f4ada15SMatthew G. Knepley } 54423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5443552f7358SJed Brown } 5444552f7358SJed Brown 5445552f7358SJed Brown /*@ 544620f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5447552f7358SJed Brown 5448552f7358SJed Brown Not Collective 5449552f7358SJed Brown 5450552f7358SJed Brown Input Parameters: 5451a1cb98faSBarry Smith + dm - The `DMPLEX` object 5452570fa34dSVaclav Hapla - depth - The requested depth 5453552f7358SJed Brown 5454552f7358SJed Brown Output Parameters: 545520f4b53cSBarry Smith + start - The first point at this `depth` 545620f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5457552f7358SJed Brown 5458552f7358SJed Brown Level: developer 5459552f7358SJed Brown 5460a1cb98faSBarry Smith Notes: 5461a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5462a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5463a1cb98faSBarry Smith higher dimension, e.g., "edges". 5464a1cb98faSBarry Smith 54652827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5466552f7358SJed Brown @*/ 5467ce78bad3SBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PeOp PetscInt *start, PeOp PetscInt *end) 5468d71ae5a4SJacob Faibussowitsch { 54699f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5470aa50250dSMatthew G. Knepley DMLabel label; 547163d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5472552f7358SJed Brown 5473552f7358SJed Brown PetscFunctionBegin; 5474552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54759371c9d4SSatish Balay if (start) { 54764f572ea9SToby Isaac PetscAssertPointer(start, 3); 54779371c9d4SSatish Balay *start = 0; 54789371c9d4SSatish Balay } 54799371c9d4SSatish Balay if (end) { 54804f572ea9SToby Isaac PetscAssertPointer(end, 4); 54819371c9d4SSatish Balay *end = 0; 54829371c9d4SSatish Balay } 54839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 54843ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5485570fa34dSVaclav Hapla if (depth < 0) { 548663d1a920SMatthew G. Knepley if (start) *start = pStart; 548763d1a920SMatthew G. Knepley if (end) *end = pEnd; 54883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5489552f7358SJed Brown } 54909f4ada15SMatthew G. Knepley if (mesh->tr) { 54919f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 54929f4ada15SMatthew G. Knepley } else { 54939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 549428b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5495570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 54969f4ada15SMatthew G. Knepley } 54973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5498552f7358SJed Brown } 5499552f7358SJed Brown 5500552f7358SJed Brown /*@ 550120f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5502552f7358SJed Brown 5503552f7358SJed Brown Not Collective 5504552f7358SJed Brown 5505552f7358SJed Brown Input Parameters: 5506a1cb98faSBarry Smith + dm - The `DMPLEX` object 5507570fa34dSVaclav Hapla - height - The requested height 5508552f7358SJed Brown 5509552f7358SJed Brown Output Parameters: 551020f4b53cSBarry Smith + start - The first point at this `height` 551120f4b53cSBarry Smith - end - One beyond the last point at this `height` 5512552f7358SJed Brown 5513552f7358SJed Brown Level: developer 5514552f7358SJed Brown 5515a1cb98faSBarry Smith Notes: 5516a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5517a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5518a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5519a1cb98faSBarry Smith 55202827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5521552f7358SJed Brown @*/ 5522ce78bad3SBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PeOp PetscInt *start, PeOp PetscInt *end) 5523d71ae5a4SJacob Faibussowitsch { 5524aa50250dSMatthew G. Knepley DMLabel label; 552563d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5526552f7358SJed Brown 5527552f7358SJed Brown PetscFunctionBegin; 5528552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55299371c9d4SSatish Balay if (start) { 55304f572ea9SToby Isaac PetscAssertPointer(start, 3); 55319371c9d4SSatish Balay *start = 0; 55329371c9d4SSatish Balay } 55339371c9d4SSatish Balay if (end) { 55344f572ea9SToby Isaac PetscAssertPointer(end, 4); 55359371c9d4SSatish Balay *end = 0; 55369371c9d4SSatish Balay } 55379566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 55383ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5539570fa34dSVaclav Hapla if (height < 0) { 554063d1a920SMatthew G. Knepley if (start) *start = pStart; 554163d1a920SMatthew G. Knepley if (end) *end = pEnd; 55423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5543552f7358SJed Brown } 55449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 554559e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 554659e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 554759e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 554859e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 55493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5550552f7358SJed Brown } 5551552f7358SJed Brown 5552ba2698f1SMatthew G. Knepley /*@ 555320f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5554ba2698f1SMatthew G. Knepley 5555ba2698f1SMatthew G. Knepley Not Collective 5556ba2698f1SMatthew G. Knepley 5557d8d19677SJose E. Roman Input Parameters: 5558a1cb98faSBarry Smith + dm - The `DMPLEX` object 5559ba2698f1SMatthew G. Knepley - point - The point 5560ba2698f1SMatthew G. Knepley 5561ba2698f1SMatthew G. Knepley Output Parameter: 556220f4b53cSBarry Smith . depth - The depth of the `point` 5563ba2698f1SMatthew G. Knepley 5564ba2698f1SMatthew G. Knepley Level: intermediate 5565ba2698f1SMatthew G. Knepley 55661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5567ba2698f1SMatthew G. Knepley @*/ 5568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5569d71ae5a4SJacob Faibussowitsch { 5570ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5571ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55724f572ea9SToby Isaac PetscAssertPointer(depth, 3); 55739566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 55743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5575ba2698f1SMatthew G. Knepley } 5576ba2698f1SMatthew G. Knepley 5577ba2698f1SMatthew G. Knepley /*@ 557820f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 55790c0a32dcSVaclav Hapla 55800c0a32dcSVaclav Hapla Not Collective 55810c0a32dcSVaclav Hapla 5582d8d19677SJose E. Roman Input Parameters: 5583a1cb98faSBarry Smith + dm - The `DMPLEX` object 55840c0a32dcSVaclav Hapla - point - The point 55850c0a32dcSVaclav Hapla 55860c0a32dcSVaclav Hapla Output Parameter: 558720f4b53cSBarry Smith . height - The height of the `point` 55880c0a32dcSVaclav Hapla 55890c0a32dcSVaclav Hapla Level: intermediate 55900c0a32dcSVaclav Hapla 55911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 55920c0a32dcSVaclav Hapla @*/ 5593d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5594d71ae5a4SJacob Faibussowitsch { 55950c0a32dcSVaclav Hapla PetscInt n, pDepth; 55960c0a32dcSVaclav Hapla 55970c0a32dcSVaclav Hapla PetscFunctionBegin; 55980c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55994f572ea9SToby Isaac PetscAssertPointer(height, 3); 56009566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 56019566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 56020c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 56033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56040c0a32dcSVaclav Hapla } 56050c0a32dcSVaclav Hapla 56060c0a32dcSVaclav Hapla /*@ 5607a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5608ba2698f1SMatthew G. Knepley 5609ba2698f1SMatthew G. Knepley Not Collective 5610ba2698f1SMatthew G. Knepley 5611ba2698f1SMatthew G. Knepley Input Parameter: 5612a1cb98faSBarry Smith . dm - The `DMPLEX` object 5613ba2698f1SMatthew G. Knepley 5614ba2698f1SMatthew G. Knepley Output Parameter: 5615a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5616412e9a14SMatthew G. Knepley 5617ba2698f1SMatthew G. Knepley Level: developer 5618ba2698f1SMatthew G. Knepley 5619a1cb98faSBarry Smith Note: 5620a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5621a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5622a1cb98faSBarry Smith 56231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5624ba2698f1SMatthew G. Knepley @*/ 5625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5626d71ae5a4SJacob Faibussowitsch { 5627ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5628ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56294f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 56309566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5631ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 56323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5633ba2698f1SMatthew G. Knepley } 5634ba2698f1SMatthew G. Knepley 5635ba2698f1SMatthew G. Knepley /*@ 5636ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5637ba2698f1SMatthew G. Knepley 5638ba2698f1SMatthew G. Knepley Not Collective 5639ba2698f1SMatthew G. Knepley 5640d8d19677SJose E. Roman Input Parameters: 5641a1cb98faSBarry Smith + dm - The `DMPLEX` object 5642ba2698f1SMatthew G. Knepley - cell - The cell 5643ba2698f1SMatthew G. Knepley 5644ba2698f1SMatthew G. Knepley Output Parameter: 5645ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5646ba2698f1SMatthew G. Knepley 5647ba2698f1SMatthew G. Knepley Level: intermediate 5648ba2698f1SMatthew G. Knepley 56491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5650ba2698f1SMatthew G. Knepley @*/ 5651d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5652d71ae5a4SJacob Faibussowitsch { 56539f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5654ba2698f1SMatthew G. Knepley DMLabel label; 5655ba2698f1SMatthew G. Knepley PetscInt ct; 5656ba2698f1SMatthew G. Knepley 5657ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5658ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56594f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 56609f4ada15SMatthew G. Knepley if (mesh->tr) { 56619f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 56629f4ada15SMatthew G. Knepley } else { 566321027e53SStefano Zampini PetscInt pStart, pEnd; 566421027e53SStefano Zampini 566521027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 566621027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 566721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 5668f4a55318SMatthew G. Knepley if (pEnd <= pStart) { 5669f4a55318SMatthew G. Knepley *celltype = DM_POLYTOPE_UNKNOWN; 5670f4a55318SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5671f4a55318SMatthew G. Knepley } 567221027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 567321027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 567421027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 567521027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 56766497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 567721027e53SStefano Zampini } 567821027e53SStefano Zampini } 567921027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 568021027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 56819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 56829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 568363a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5684936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 568521027e53SStefano Zampini } 56869f4ada15SMatthew G. Knepley } 56873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5688ba2698f1SMatthew G. Knepley } 5689ba2698f1SMatthew G. Knepley 5690412e9a14SMatthew G. Knepley /*@ 5691412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5692412e9a14SMatthew G. Knepley 5693412e9a14SMatthew G. Knepley Not Collective 5694412e9a14SMatthew G. Knepley 5695412e9a14SMatthew G. Knepley Input Parameters: 5696a1cb98faSBarry Smith + dm - The `DMPLEX` object 5697412e9a14SMatthew G. Knepley . cell - The cell 5698412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5699412e9a14SMatthew G. Knepley 5700a1cb98faSBarry Smith Level: advanced 5701a1cb98faSBarry Smith 5702a1cb98faSBarry Smith Note: 5703a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5704412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5705412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5706db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5707412e9a14SMatthew G. Knepley 57081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5709412e9a14SMatthew G. Knepley @*/ 5710d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5711d71ae5a4SJacob Faibussowitsch { 571221027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5713412e9a14SMatthew G. Knepley DMLabel label; 571421027e53SStefano Zampini PetscInt pStart, pEnd; 5715412e9a14SMatthew G. Knepley 5716412e9a14SMatthew G. Knepley PetscFunctionBegin; 5717412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 571821027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 57199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 57209566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 572121027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 57226497c311SBarry Smith mesh->cellTypes[cell - pStart].value_as_uint8 = (uint8_t)celltype; 57233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5724412e9a14SMatthew G. Knepley } 5725412e9a14SMatthew G. Knepley 5726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5727d71ae5a4SJacob Faibussowitsch { 5728c789d87fSToby Isaac PetscSection section; 57293e922f36SToby Isaac PetscInt maxHeight; 5730dd4c3f67SMatthew G. Knepley const char *prefix; 5731552f7358SJed Brown 5732552f7358SJed Brown PetscFunctionBegin; 57339566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5734dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5735dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5736dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 57379566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 57389566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 57399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 57409566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 57419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 57428f4c458bSMatthew G. Knepley 57439566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 57449566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5745dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5746dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 57473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5748552f7358SJed Brown } 5749552f7358SJed Brown 575099acd26cSksagiyam PetscErrorCode DMCreateCellCoordinateDM_Plex(DM dm, DM *cdm) 575199acd26cSksagiyam { 575299acd26cSksagiyam DM cgcdm; 575399acd26cSksagiyam PetscSection section; 575499acd26cSksagiyam const char *prefix; 575599acd26cSksagiyam 575699acd26cSksagiyam PetscFunctionBegin; 575799acd26cSksagiyam PetscCall(DMGetCoordinateDM(dm, &cgcdm)); 575899acd26cSksagiyam PetscCall(DMClone(cgcdm, cdm)); 575999acd26cSksagiyam PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 576099acd26cSksagiyam PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 576199acd26cSksagiyam PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cellcdm_")); 576299acd26cSksagiyam PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 576399acd26cSksagiyam PetscCall(DMSetLocalSection(*cdm, section)); 576499acd26cSksagiyam PetscCall(PetscSectionDestroy(§ion)); 576599acd26cSksagiyam PetscCall(DMSetNumFields(*cdm, 1)); 576699acd26cSksagiyam PetscCall(DMCreateDS(*cdm)); 576799acd26cSksagiyam (*cdm)->cloneOpts = PETSC_TRUE; 576899acd26cSksagiyam if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 576999acd26cSksagiyam PetscFunctionReturn(PETSC_SUCCESS); 577099acd26cSksagiyam } 577199acd26cSksagiyam 5772d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5773d71ae5a4SJacob Faibussowitsch { 57746858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 57756858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5776f19dbd58SToby Isaac 5777f19dbd58SToby Isaac PetscFunctionBegin; 5778f19dbd58SToby Isaac *field = NULL; 57799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 57809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 57816858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 57826858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5783f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 57846858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 57856858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5786f19dbd58SToby Isaac } 57873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5788f19dbd58SToby Isaac } 5789f19dbd58SToby Isaac 5790cc4c1da9SBarry Smith /*@ 57917cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 57927cd05799SMatthew G. Knepley 57937cd05799SMatthew G. Knepley Not Collective 57947cd05799SMatthew G. Knepley 57952fe279fdSBarry Smith Input Parameter: 5796a1cb98faSBarry Smith . dm - The `DMPLEX` object 57977cd05799SMatthew G. Knepley 57987cd05799SMatthew G. Knepley Output Parameter: 5799a1cb98faSBarry Smith . section - The `PetscSection` object 58007cd05799SMatthew G. Knepley 58017cd05799SMatthew G. Knepley Level: developer 58027cd05799SMatthew G. Knepley 58031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 58047cd05799SMatthew G. Knepley @*/ 5805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5806d71ae5a4SJacob Faibussowitsch { 5807552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5808552f7358SJed Brown 5809552f7358SJed Brown PetscFunctionBegin; 5810552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5811552f7358SJed Brown if (section) *section = mesh->coneSection; 58123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5813552f7358SJed Brown } 5814552f7358SJed Brown 5815cc4c1da9SBarry Smith /*@ 58167cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 58177cd05799SMatthew G. Knepley 58187cd05799SMatthew G. Knepley Not Collective 58197cd05799SMatthew G. Knepley 58202fe279fdSBarry Smith Input Parameter: 5821a1cb98faSBarry Smith . dm - The `DMPLEX` object 58227cd05799SMatthew G. Knepley 58237cd05799SMatthew G. Knepley Output Parameter: 5824a1cb98faSBarry Smith . section - The `PetscSection` object 58257cd05799SMatthew G. Knepley 58267cd05799SMatthew G. Knepley Level: developer 58277cd05799SMatthew G. Knepley 58281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 58297cd05799SMatthew G. Knepley @*/ 5830d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5831d71ae5a4SJacob Faibussowitsch { 58328cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 58338cb4d582SMatthew G. Knepley 58348cb4d582SMatthew G. Knepley PetscFunctionBegin; 58358cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58368cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 58373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58388cb4d582SMatthew G. Knepley } 58398cb4d582SMatthew G. Knepley 58407cd05799SMatthew G. Knepley /*@C 58417cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 58427cd05799SMatthew G. Knepley 58437cd05799SMatthew G. Knepley Not Collective 58447cd05799SMatthew G. Knepley 58452fe279fdSBarry Smith Input Parameter: 5846a1cb98faSBarry Smith . dm - The `DMPLEX` object 58477cd05799SMatthew G. Knepley 58487cd05799SMatthew G. Knepley Output Parameter: 58497cd05799SMatthew G. Knepley . cones - The cone for each point 58507cd05799SMatthew G. Knepley 58517cd05799SMatthew G. Knepley Level: developer 58527cd05799SMatthew G. Knepley 58531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 58547cd05799SMatthew G. Knepley @*/ 5855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5856d71ae5a4SJacob Faibussowitsch { 5857552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5858552f7358SJed Brown 5859552f7358SJed Brown PetscFunctionBegin; 5860552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5861552f7358SJed Brown if (cones) *cones = mesh->cones; 58623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5863552f7358SJed Brown } 5864552f7358SJed Brown 58657cd05799SMatthew G. Knepley /*@C 58667cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 58677cd05799SMatthew G. Knepley 58687cd05799SMatthew G. Knepley Not Collective 58697cd05799SMatthew G. Knepley 58702fe279fdSBarry Smith Input Parameter: 5871a1cb98faSBarry Smith . dm - The `DMPLEX` object 58727cd05799SMatthew G. Knepley 58737cd05799SMatthew G. Knepley Output Parameter: 5874b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 58757cd05799SMatthew G. Knepley 58767cd05799SMatthew G. Knepley Level: developer 58777cd05799SMatthew G. Knepley 5878b5a892a1SMatthew G. Knepley Notes: 58792c9a7b26SBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points 58802c9a7b26SBarry Smith as returned by `DMPlexGetConeOrientation()`. 5881b5a892a1SMatthew G. Knepley 5882a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5883b5a892a1SMatthew G. Knepley 58841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 58857cd05799SMatthew G. Knepley @*/ 5886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5887d71ae5a4SJacob Faibussowitsch { 5888552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5889552f7358SJed Brown 5890552f7358SJed Brown PetscFunctionBegin; 5891552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5892552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 58933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5894552f7358SJed Brown } 5895552f7358SJed Brown 58964ee01570SBarry Smith /* FEM Support */ 5897552f7358SJed Brown 5898d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5899d2b2dc1eSMatthew G. Knepley { 5900d2b2dc1eSMatthew G. Knepley PetscInt depth; 5901d2b2dc1eSMatthew G. Knepley 5902d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5903d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5904d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5905d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5906d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5907d2b2dc1eSMatthew G. Knepley } 5908d2b2dc1eSMatthew G. Knepley 59095962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 59105962854dSMatthew G. Knepley { 59115962854dSMatthew G. Knepley PetscInt depth; 59125962854dSMatthew G. Knepley 59135962854dSMatthew G. Knepley PetscFunctionBegin; 59145962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 59155962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 59165962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 59175962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 59185962854dSMatthew G. Knepley } 59195962854dSMatthew G. Knepley 59209e8305c2SJed Brown /* 59219e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 59229e8305c2SJed Brown representing a line in the section. 59239e8305c2SJed Brown */ 59245f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5925d71ae5a4SJacob Faibussowitsch { 5926e327e467SRezgar Shakeri PetscObject obj; 5927e327e467SRezgar Shakeri PetscClassId id; 5928e327e467SRezgar Shakeri PetscFE fe = NULL; 5929e327e467SRezgar Shakeri 59309e8305c2SJed Brown PetscFunctionBeginHot; 59319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5932e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5933e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5934e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5935e327e467SRezgar Shakeri 5936e327e467SRezgar Shakeri if (!fe) { 5937e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 59389e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 59399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 59409e8305c2SJed Brown *k = *k / *Nc + 1; 5941e327e467SRezgar Shakeri } else { 5942e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 59435f82726aSMatthew G. Knepley PetscDualSpace dsp; 59445f82726aSMatthew G. Knepley 5945e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 59465f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 59475f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5948e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 59495f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 59505f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 59515f82726aSMatthew G. Knepley } 59525f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 59535f82726aSMatthew G. Knepley } 59545f82726aSMatthew G. Knepley 59555f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 59565f82726aSMatthew G. Knepley { 59575f82726aSMatthew G. Knepley PetscFunctionBeginHot; 59585f82726aSMatthew G. Knepley if (tensor) { 59595f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 59605f82726aSMatthew G. Knepley } else { 59615f82726aSMatthew G. Knepley switch (dim) { 59625f82726aSMatthew G. Knepley case 1: 59635f82726aSMatthew G. Knepley *dof = k + 1; 59645f82726aSMatthew G. Knepley break; 59655f82726aSMatthew G. Knepley case 2: 59665f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 59675f82726aSMatthew G. Knepley break; 59685f82726aSMatthew G. Knepley case 3: 59695f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 59705f82726aSMatthew G. Knepley break; 59715f82726aSMatthew G. Knepley default: 59725f82726aSMatthew G. Knepley *dof = 0; 59735f82726aSMatthew G. Knepley } 59749e8305c2SJed Brown } 59753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59769e8305c2SJed Brown } 59779e8305c2SJed Brown 5978a4355906SMatthew Knepley /*@ 5979bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5980bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 598120f4b53cSBarry Smith section provided (or the section of the `DM`). 5982a4355906SMatthew Knepley 5983a4355906SMatthew Knepley Input Parameters: 598420f4b53cSBarry Smith + dm - The `DM` 598520f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 598620f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5987a4355906SMatthew Knepley 5988bc1eb3faSJed Brown Example: 5989bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5990bc1eb3faSJed Brown .vb 5991bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5992bc1eb3faSJed Brown 5993bc1eb3faSJed Brown v4 -- e6 -- v3 5994bc1eb3faSJed Brown | | 5995bc1eb3faSJed Brown e7 c0 e8 5996bc1eb3faSJed Brown | | 5997bc1eb3faSJed Brown v1 -- e5 -- v2 5998bc1eb3faSJed Brown .ve 5999bc1eb3faSJed Brown 6000bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 6001bc1eb3faSJed Brown dofs in the order of points, e.g., 6002bc1eb3faSJed Brown .vb 6003bc1eb3faSJed Brown c0 -> [0,1,2,3] 6004bc1eb3faSJed Brown v1 -> [4] 6005bc1eb3faSJed Brown ... 6006bc1eb3faSJed Brown e5 -> [8, 9] 6007bc1eb3faSJed Brown .ve 6008bc1eb3faSJed Brown 6009bc1eb3faSJed Brown which corresponds to the dofs 6010bc1eb3faSJed Brown .vb 6011bc1eb3faSJed Brown 6 10 11 7 6012bc1eb3faSJed Brown 13 2 3 15 6013bc1eb3faSJed Brown 12 0 1 14 6014bc1eb3faSJed Brown 4 8 9 5 6015bc1eb3faSJed Brown .ve 6016bc1eb3faSJed Brown 6017bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 6018bc1eb3faSJed Brown .vb 6019bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 6020bc1eb3faSJed Brown .ve 6021bc1eb3faSJed Brown 6022bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 6023bc1eb3faSJed Brown .vb 6024bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 6025bc1eb3faSJed Brown .ve 6026bc1eb3faSJed Brown 6027a4355906SMatthew Knepley Level: developer 6028a4355906SMatthew Knepley 6029da9ac489SAlbert Cowie Notes: 6030a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 6031a1cb98faSBarry Smith degree of the basis. 6032a1cb98faSBarry Smith 6033da9ac489SAlbert Cowie This is required to run with libCEED. 6034da9ac489SAlbert Cowie 60351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 6036a4355906SMatthew Knepley @*/ 6037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 6038d71ae5a4SJacob Faibussowitsch { 60397391a63aSMatthew G. Knepley DMLabel label; 6040bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 60415f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 60423194fc30SMatthew G. Knepley 60433194fc30SMatthew G. Knepley PetscFunctionBegin; 60449566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 60453ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 6046a433471fSStefano Zampini if (point < 0) { 6047a433471fSStefano Zampini PetscInt sStart, sEnd; 6048a433471fSStefano Zampini 60499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 6050a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 6051a433471fSStefano Zampini } 60529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 60539566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 60549566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 60559371c9d4SSatish Balay if (depth == 1) { 60569371c9d4SSatish Balay eStart = point; 60579371c9d4SSatish Balay } else if (depth == dim) { 60587391a63aSMatthew G. Knepley const PetscInt *cone; 60597391a63aSMatthew G. Knepley 60609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 6061d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 6062d4e6627bSStefano Zampini else if (dim == 3) { 6063d4e6627bSStefano Zampini const PetscInt *cone2; 60649566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 6065d4e6627bSStefano Zampini eStart = cone2[0]; 606663a3b9bcSJacob 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); 606763a3b9bcSJacob 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); 6068e327e467SRezgar Shakeri 60699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 6070bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 6071bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 6072bb197d40SJed Brown PetscInt *perm; 6073bb197d40SJed Brown 60743194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 60755f82726aSMatthew G. Knepley PetscInt dof; 60765f82726aSMatthew G. Knepley 60775f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60785f82726aSMatthew 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); 60795f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 60805f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60815f82726aSMatthew G. Knepley size += dof * Nc; 60823194fc30SMatthew G. Knepley } 60839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 60843194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 6085bb197d40SJed Brown switch (d) { 6086babf31e0SJed Brown case 1: 60875f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60885f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 6089babf31e0SJed Brown /* 6090babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 6091babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 6092babf31e0SJed Brown */ 6093e327e467SRezgar Shakeri if (continuous) { 6094babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 60959371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 60969371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 6097babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 6098babf31e0SJed Brown foffset = offset; 6099e327e467SRezgar Shakeri } else { 61005f82726aSMatthew G. Knepley PetscInt dof; 61015f82726aSMatthew G. Knepley 61025f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 61035f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 61045f82726aSMatthew G. Knepley foffset = offset; 6105e327e467SRezgar Shakeri } 6106babf31e0SJed Brown break; 610789eabcffSMatthew G. Knepley case 2: 61083194fc30SMatthew 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} */ 61095f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 61105f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 61113194fc30SMatthew G. Knepley /* The SEM order is 61123194fc30SMatthew G. Knepley 61133194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 611489eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 61153194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 61163194fc30SMatthew G. Knepley */ 6117e327e467SRezgar Shakeri if (continuous) { 61183194fc30SMatthew G. Knepley const PetscInt of = 0; 61193194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 61203194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 61213194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 61223194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 61233194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 61243194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 61253194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 61263194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 61273194fc30SMatthew G. Knepley PetscInt o; 61283194fc30SMatthew G. Knepley 61293194fc30SMatthew G. Knepley /* bottom */ 61303194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 61319371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 61329371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61333194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 61343194fc30SMatthew G. Knepley /* middle */ 61353194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 61363194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 61379371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 61389371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61393194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 61403194fc30SMatthew G. Knepley } 61413194fc30SMatthew G. Knepley /* top */ 61423194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 61439371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 61449371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61453194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 61463194fc30SMatthew G. Knepley foffset = offset; 6147e327e467SRezgar Shakeri } else { 61485f82726aSMatthew G. Knepley PetscInt dof; 61495f82726aSMatthew G. Knepley 61505f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 61515f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 61525f82726aSMatthew G. Knepley foffset = offset; 61533194fc30SMatthew G. Knepley } 615489eabcffSMatthew G. Knepley break; 615589eabcffSMatthew G. Knepley case 3: 615689eabcffSMatthew G. Knepley /* The original hex closure is 615789eabcffSMatthew G. Knepley 615889eabcffSMatthew G. Knepley {c, 615989eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 616089eabcffSMatthew 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, 616189eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 616289eabcffSMatthew G. Knepley */ 61635f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 61645f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 616589eabcffSMatthew G. Knepley /* The SEM order is 616689eabcffSMatthew G. Knepley Bottom Slice 616789eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 616889eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 616989eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 617089eabcffSMatthew G. Knepley 617189eabcffSMatthew G. Knepley Middle Slice (j) 617289eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 617389eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 617489eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 617589eabcffSMatthew G. Knepley 617689eabcffSMatthew G. Knepley Top Slice 617789eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 617889eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 617989eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 618089eabcffSMatthew G. Knepley */ 6181e327e467SRezgar Shakeri if (continuous) { 618289eabcffSMatthew G. Knepley const PetscInt oc = 0; 618389eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 618489eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 618589eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 618689eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 618789eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 618889eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 618989eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 619089eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 619189eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 619289eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 619389eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 619489eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 619589eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 619689eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 619789eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 619889eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 619989eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 620089eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 620189eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 620289eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 620389eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 620489eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 620589eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 620689eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 620789eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 620889eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 620989eabcffSMatthew G. Knepley PetscInt o, n; 621089eabcffSMatthew G. Knepley 621189eabcffSMatthew G. Knepley /* Bottom Slice */ 621289eabcffSMatthew G. Knepley /* bottom */ 621389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 62149371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 62159371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 621689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 621789eabcffSMatthew G. Knepley /* middle */ 621889eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 621989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 62209371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 62219371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 62229371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 62239371c9d4SSatish Balay } 622489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 62253194fc30SMatthew G. Knepley } 622689eabcffSMatthew G. Knepley /* top */ 622789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 62289371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 62299371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 623089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 623189eabcffSMatthew G. Knepley 623289eabcffSMatthew G. Knepley /* Middle Slice */ 623389eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 623489eabcffSMatthew G. Knepley /* bottom */ 623589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 62369371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 62379371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 623889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 623989eabcffSMatthew G. Knepley /* middle */ 624089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 624189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 62429371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 62439371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 624489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 624589eabcffSMatthew G. Knepley } 624689eabcffSMatthew G. Knepley /* top */ 624789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 62489371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 62499371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 625089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 625189eabcffSMatthew G. Knepley } 625289eabcffSMatthew G. Knepley 625389eabcffSMatthew G. Knepley /* Top Slice */ 625489eabcffSMatthew G. Knepley /* bottom */ 625589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 62569371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 62579371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 625889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 625989eabcffSMatthew G. Knepley /* middle */ 626089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 626189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 62629371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 62639371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 626489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 626589eabcffSMatthew G. Knepley } 626689eabcffSMatthew G. Knepley /* top */ 626789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 62689371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 62699371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 627089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 627189eabcffSMatthew G. Knepley 627289eabcffSMatthew G. Knepley foffset = offset; 6273e327e467SRezgar Shakeri } else { 62745f82726aSMatthew G. Knepley PetscInt dof; 62755f82726aSMatthew G. Knepley 62765f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 62775f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 62785f82726aSMatthew G. Knepley foffset = offset; 627989eabcffSMatthew G. Knepley } 628089eabcffSMatthew G. Knepley break; 6281d71ae5a4SJacob Faibussowitsch default: 6282d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 628389eabcffSMatthew G. Knepley } 628489eabcffSMatthew G. Knepley } 628563a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 62863194fc30SMatthew G. Knepley /* Check permutation */ 62873194fc30SMatthew G. Knepley { 62883194fc30SMatthew G. Knepley PetscInt *check; 62893194fc30SMatthew G. Knepley 62909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 62911dca8a05SBarry Smith for (i = 0; i < size; ++i) { 62921dca8a05SBarry Smith check[i] = -1; 62931dca8a05SBarry 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]); 62941dca8a05SBarry Smith } 62953194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 62961dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 62979566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 62983194fc30SMatthew G. Knepley } 62999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6300a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6301a05c9aa3SJed Brown PetscInt *loc_perm; 63029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6303a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6304a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6305a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6306a05c9aa3SJed Brown } 63079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6308a05c9aa3SJed Brown } 6309bb197d40SJed Brown } 63103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63113194fc30SMatthew G. Knepley } 63123194fc30SMatthew G. Knepley 6313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6314d71ae5a4SJacob Faibussowitsch { 6315e071409bSToby Isaac PetscDS prob; 6316e071409bSToby Isaac PetscInt depth, Nf, h; 6317e071409bSToby Isaac DMLabel label; 6318e071409bSToby Isaac 6319e071409bSToby Isaac PetscFunctionBeginHot; 63209566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6321e071409bSToby Isaac Nf = prob->Nf; 6322e071409bSToby Isaac label = dm->depthLabel; 6323e071409bSToby Isaac *dspace = NULL; 6324e071409bSToby Isaac if (field < Nf) { 6325e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6326e071409bSToby Isaac 6327e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6328e071409bSToby Isaac PetscDualSpace dsp; 6329e071409bSToby Isaac 63309566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 63319566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 63329566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6333e071409bSToby Isaac h = depth - 1 - h; 6334e071409bSToby Isaac if (h) { 63359566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6336e071409bSToby Isaac } else { 6337e071409bSToby Isaac *dspace = dsp; 6338e071409bSToby Isaac } 6339e071409bSToby Isaac } 6340e071409bSToby Isaac } 63413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6342e071409bSToby Isaac } 6343e071409bSToby Isaac 6344d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6345d71ae5a4SJacob Faibussowitsch { 634628351e22SJed Brown PetscScalar *array; 634728351e22SJed Brown const PetscScalar *vArray; 6348d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 63491a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6350552f7358SJed Brown 63511b406b76SMatthew G. Knepley PetscFunctionBeginHot; 63529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 63539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 63549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 63559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 63563f7cbbe7SMatthew G. Knepley if (!values || !*values) { 63579df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 63589df71ca4SMatthew G. Knepley PetscInt dof; 6359d9917b9dSMatthew G. Knepley 63609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 63619df71ca4SMatthew G. Knepley size += dof; 63629df71ca4SMatthew G. Knepley } 63639df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 63649df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 63652a3aaacfSMatthew G. Knepley PetscInt dof; 63665a1bb5cfSMatthew G. Knepley 63675a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 63689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 63695a1bb5cfSMatthew G. Knepley size += dof; 63705a1bb5cfSMatthew G. Knepley } 63713f7cbbe7SMatthew G. Knepley if (!values) { 63723f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 63733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63743f7cbbe7SMatthew G. Knepley } 63759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6376982e9ed1SMatthew G. Knepley } else { 6377982e9ed1SMatthew G. Knepley array = *values; 6378982e9ed1SMatthew G. Knepley } 63799df71ca4SMatthew G. Knepley size = 0; 638028351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 63819df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 63829df71ca4SMatthew G. Knepley PetscInt dof, off, d; 638328351e22SJed Brown const PetscScalar *varr; 6384d9917b9dSMatthew G. Knepley 63859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 63869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 63878e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6388ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 63899df71ca4SMatthew G. Knepley size += dof; 63909df71ca4SMatthew G. Knepley } 63919df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 63929df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 63939df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 63945a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 639528351e22SJed Brown const PetscScalar *varr; 63965a1bb5cfSMatthew G. Knepley 639752ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 63989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 63999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 64008e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 64015a1bb5cfSMatthew G. Knepley if (o >= 0) { 6402ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 64035a1bb5cfSMatthew G. Knepley } else { 6404ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 64055a1bb5cfSMatthew G. Knepley } 64069df71ca4SMatthew G. Knepley size += dof; 64075a1bb5cfSMatthew G. Knepley } 640828351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 64099df71ca4SMatthew G. Knepley if (!*values) { 64105a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 64115a1bb5cfSMatthew G. Knepley *values = array; 64129df71ca4SMatthew G. Knepley } else { 641363a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 64148c312ff3SMatthew G. Knepley *csize = size; 64159df71ca4SMatthew G. Knepley } 64163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64175a1bb5cfSMatthew G. Knepley } 6418d9917b9dSMatthew G. Knepley 641927f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6420d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6421d71ae5a4SJacob Faibussowitsch { 642227f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 642327f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 642427f02ce8SMatthew G. Knepley 64259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 642627f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 642727f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 642827f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 642927f02ce8SMatthew G. Knepley points[q * 2] = r; 643027f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 643127f02ce8SMatthew G. Knepley ++q; 643227f02ce8SMatthew G. Knepley } 643327f02ce8SMatthew G. Knepley } 643427f02ce8SMatthew G. Knepley *numPoints = q; 64353ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 643627f02ce8SMatthew G. Knepley } 643727f02ce8SMatthew G. Knepley 643897529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 643907218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6440d71ae5a4SJacob Faibussowitsch { 644127f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6442923c78e0SToby Isaac PetscInt np, *pts = NULL; 6443923c78e0SToby Isaac 6444923c78e0SToby Isaac PetscFunctionBeginHot; 64459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 644607218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6447923c78e0SToby Isaac PetscInt dof, off; 6448923c78e0SToby Isaac 64499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 64509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 64519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6452923c78e0SToby Isaac np = dof / 2; 64538e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 645427f02ce8SMatthew G. Knepley } else { 645507218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 64569566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6457923c78e0SToby Isaac } 6458923c78e0SToby Isaac *numPoints = np; 6459923c78e0SToby Isaac *points = pts; 6460923c78e0SToby Isaac *clp = cla; 64613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6462923c78e0SToby Isaac } 6463923c78e0SToby Isaac 6464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6465d71ae5a4SJacob Faibussowitsch { 6466923c78e0SToby Isaac PetscFunctionBeginHot; 6467923c78e0SToby Isaac if (!*clPoints) { 64689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6469923c78e0SToby Isaac } else { 64709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6471923c78e0SToby Isaac } 6472923c78e0SToby Isaac *numPoints = 0; 6473923c78e0SToby Isaac *points = NULL; 6474923c78e0SToby Isaac *clSec = NULL; 6475923c78e0SToby Isaac *clPoints = NULL; 6476923c78e0SToby Isaac *clp = NULL; 64773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6478923c78e0SToby Isaac } 6479923c78e0SToby Isaac 6480d71ae5a4SJacob 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[]) 6481d71ae5a4SJacob Faibussowitsch { 64821a271a75SMatthew G. Knepley PetscInt offset = 0, p; 648397e99dd9SToby Isaac const PetscInt **perms = NULL; 648497e99dd9SToby Isaac const PetscScalar **flips = NULL; 64851a271a75SMatthew G. Knepley 64861a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6487fe02ba77SJed Brown *size = 0; 64889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 648997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 649097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 649197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 649297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64931a271a75SMatthew G. Knepley PetscInt dof, off, d; 64941a271a75SMatthew G. Knepley const PetscScalar *varr; 64951a271a75SMatthew G. Knepley 64969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 64979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 64988e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 649997e99dd9SToby Isaac if (clperm) { 650097e99dd9SToby Isaac if (perm) { 650197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 65021a271a75SMatthew G. Knepley } else { 650397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 650497e99dd9SToby Isaac } 650597e99dd9SToby Isaac if (flip) { 650697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 650797e99dd9SToby Isaac } 650897e99dd9SToby Isaac } else { 650997e99dd9SToby Isaac if (perm) { 651097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 651197e99dd9SToby Isaac } else { 651297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 651397e99dd9SToby Isaac } 651497e99dd9SToby Isaac if (flip) { 651597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 65161a271a75SMatthew G. Knepley } 65171a271a75SMatthew G. Knepley } 651897e99dd9SToby Isaac offset += dof; 651997e99dd9SToby Isaac } 65209566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 65211a271a75SMatthew G. Knepley *size = offset; 65223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65231a271a75SMatthew G. Knepley } 65241a271a75SMatthew G. Knepley 6525d71ae5a4SJacob 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[]) 6526d71ae5a4SJacob Faibussowitsch { 65271a271a75SMatthew G. Knepley PetscInt offset = 0, f; 65281a271a75SMatthew G. Knepley 65291a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6530fe02ba77SJed Brown *size = 0; 65311a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 653297e99dd9SToby Isaac PetscInt p; 653397e99dd9SToby Isaac const PetscInt **perms = NULL; 653497e99dd9SToby Isaac const PetscScalar **flips = NULL; 65351a271a75SMatthew G. Knepley 65369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 653797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 653897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 653997e99dd9SToby Isaac PetscInt fdof, foff, b; 65401a271a75SMatthew G. Knepley const PetscScalar *varr; 654197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 654297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 65431a271a75SMatthew G. Knepley 65449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 65459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 65461a271a75SMatthew G. Knepley varr = &vArray[foff]; 654797e99dd9SToby Isaac if (clperm) { 65489371c9d4SSatish Balay if (perm) { 6549ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 65501a271a75SMatthew G. Knepley } else { 6551ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 65529371c9d4SSatish Balay } 65539371c9d4SSatish Balay if (flip) { 6554ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 65559371c9d4SSatish Balay } 65569371c9d4SSatish Balay } else { 65579371c9d4SSatish Balay if (perm) { 6558ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 65599371c9d4SSatish Balay } else { 6560ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 65619371c9d4SSatish Balay } 65629371c9d4SSatish Balay if (flip) { 6563ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 65649371c9d4SSatish Balay } 65651a271a75SMatthew G. Knepley } 656697e99dd9SToby Isaac offset += fdof; 65671a271a75SMatthew G. Knepley } 65689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 65691a271a75SMatthew G. Knepley } 65701a271a75SMatthew G. Knepley *size = offset; 65713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65721a271a75SMatthew G. Knepley } 65731a271a75SMatthew G. Knepley 657448162695SZach Atkins /*@C 657548162695SZach Atkins DMPlexVecGetOrientedClosure - Get an array of the values on the closure of 'point' with a given orientation, optionally applying the closure permutation. 657648162695SZach Atkins 657748162695SZach Atkins Not collective 657848162695SZach Atkins 657948162695SZach Atkins Input Parameters: 658048162695SZach Atkins + dm - The `DM` 658148162695SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 658248162695SZach Atkins . useClPerm - Flag for whether the provided closure permutation should be applied to the values 658348162695SZach Atkins . v - The local vector 658448162695SZach Atkins . point - The point in the `DM` 658548162695SZach Atkins - ornt - The orientation of the cell, an integer giving the prescription for cone traversal. Typically, this will be 0. 658648162695SZach Atkins 658748162695SZach Atkins Input/Output Parameters: 658848162695SZach Atkins + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 658948162695SZach Atkins - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 659048162695SZach Atkins if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 659148162695SZach Atkins 659248162695SZach Atkins Level: advanced 659348162695SZach Atkins 659448162695SZach Atkins Notes: 659548162695SZach Atkins `DMPlexVecGetOrientedClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 659648162695SZach Atkins calling function. This is because `DMPlexVecGetOrientedClosure()` is typically called in the inner loop of a `Vec` or `Mat` 659748162695SZach Atkins assembly function, and a user may already have allocated storage for this operation. 659848162695SZach Atkins 659948162695SZach Atkins Fortran Notes: 660048162695SZach 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. 660148162695SZach Atkins In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 660248162695SZach Atkins 660348162695SZach Atkins `values` must be declared with 660448162695SZach Atkins .vb 660548162695SZach Atkins PetscScalar,dimension(:),pointer :: values 660648162695SZach Atkins .ve 660748162695SZach Atkins and it will be allocated internally by PETSc to hold the values returned 660848162695SZach Atkins 660948162695SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexGetCellCoordinates()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()` 661048162695SZach Atkins @*/ 661148162695SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 661207218a29SMatthew G. Knepley { 661307218a29SMatthew G. Knepley PetscSection clSection; 661407218a29SMatthew G. Knepley IS clPoints; 661507218a29SMatthew G. Knepley PetscInt *points = NULL; 6616e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 661707218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 661807218a29SMatthew G. Knepley 661907218a29SMatthew G. Knepley PetscFunctionBeginHot; 662007218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 662107218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 662207218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6623e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 662407218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 662507218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 662607218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 662707218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 662807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 662907218a29SMatthew G. Knepley } 663007218a29SMatthew G. Knepley /* Get points */ 663107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 663207218a29SMatthew G. Knepley /* Get sizes */ 663307218a29SMatthew G. Knepley asize = 0; 663407218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 663507218a29SMatthew G. Knepley PetscInt dof; 663607218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 663707218a29SMatthew G. Knepley asize += dof; 663807218a29SMatthew G. Knepley } 663907218a29SMatthew G. Knepley if (values) { 664007218a29SMatthew G. Knepley const PetscScalar *vArray; 664107218a29SMatthew G. Knepley PetscInt size; 664207218a29SMatthew G. Knepley 664307218a29SMatthew G. Knepley if (*values) { 664407218a29SMatthew 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); 664507218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6646e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 664707218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 664807218a29SMatthew G. Knepley /* Get values */ 664907218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 665007218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 665107218a29SMatthew 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); 665207218a29SMatthew G. Knepley /* Cleanup array */ 665307218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 665407218a29SMatthew G. Knepley } 665507218a29SMatthew G. Knepley if (csize) *csize = asize; 665607218a29SMatthew G. Knepley /* Cleanup points */ 665707218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 665807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 665907218a29SMatthew G. Knepley } 666007218a29SMatthew G. Knepley 6661552f7358SJed Brown /*@C 6662552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6663552f7358SJed Brown 6664552f7358SJed Brown Not collective 6665552f7358SJed Brown 6666552f7358SJed Brown Input Parameters: 6667a1cb98faSBarry Smith + dm - The `DM` 666820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6669552f7358SJed Brown . v - The local vector 6670a1cb98faSBarry Smith - point - The point in the `DM` 6671552f7358SJed Brown 66726b867d5aSJose E. Roman Input/Output Parameters: 667320f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 66742c9a7b26SBarry Smith - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 66752c9a7b26SBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 667622c1ee49SMatthew G. Knepley 6677552f7358SJed Brown Level: intermediate 6678552f7358SJed Brown 6679a1cb98faSBarry Smith Notes: 668044a422c4SJames Wright This is used for getting the all values in a `Vec` in the closure of a mesh point. 668144a422c4SJames Wright To get only the values in the closure of a mesh point at a specific depth (for example, at mesh vertices), use `DMPlexVecGetClosureAtDepth()`. 668244a422c4SJames Wright 668320f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6684a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6685a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6686a1cb98faSBarry Smith 6687a1cb98faSBarry Smith A typical use could be 6688a1cb98faSBarry Smith .vb 6689a1cb98faSBarry Smith values = NULL; 6690a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6691a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6692a1cb98faSBarry Smith <Compute on closure> 6693a1cb98faSBarry Smith } 6694a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6695a1cb98faSBarry Smith .ve 6696a1cb98faSBarry Smith or 6697a1cb98faSBarry Smith .vb 6698a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6699a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6700a1cb98faSBarry Smith clSize = clMaxSize; 6701a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6702a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6703a1cb98faSBarry Smith <Compute on closure> 6704a1cb98faSBarry Smith } 6705a1cb98faSBarry Smith } 6706a1cb98faSBarry Smith PetscFree(values); 6707a1cb98faSBarry Smith .ve 6708a1cb98faSBarry Smith 670960225df5SJacob Faibussowitsch Fortran Notes: 6710ce78bad3SBarry 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. 6711ce78bad3SBarry Smith In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 6712a1cb98faSBarry Smith 6713f13dfd9eSBarry Smith `values` must be declared with 6714f13dfd9eSBarry Smith .vb 6715f13dfd9eSBarry Smith PetscScalar,dimension(:),pointer :: values 6716f13dfd9eSBarry Smith .ve 6717f13dfd9eSBarry Smith and it will be allocated internally by PETSc to hold the values returned 6718f13dfd9eSBarry Smith 671944a422c4SJames Wright .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosureAtDepth()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6720552f7358SJed Brown @*/ 6721d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6722d71ae5a4SJacob Faibussowitsch { 6723d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 672448162695SZach Atkins PetscCall(DMPlexVecGetOrientedClosure(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 67253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6726552f7358SJed Brown } 6727552f7358SJed Brown 672844a422c4SJames Wright /*@C 672944a422c4SJames Wright DMPlexVecGetClosureAtDepth - Get an array of the values on the closure of 'point' that are at a specific depth 673044a422c4SJames Wright 673144a422c4SJames Wright Not collective 673244a422c4SJames Wright 673344a422c4SJames Wright Input Parameters: 673444a422c4SJames Wright + dm - The `DM` 673544a422c4SJames Wright . section - The section describing the layout in `v`, or `NULL` to use the default section 673644a422c4SJames Wright . v - The local vector 673744a422c4SJames Wright . depth - The depth of mesh points that should be returned 673844a422c4SJames Wright - point - The point in the `DM` 673944a422c4SJames Wright 674044a422c4SJames Wright Input/Output Parameters: 674144a422c4SJames Wright + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 674244a422c4SJames Wright - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 674344a422c4SJames Wright if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 674444a422c4SJames Wright 674544a422c4SJames Wright Level: intermediate 674644a422c4SJames Wright 674744a422c4SJames Wright Notes: 674844a422c4SJames Wright This is used for getting the values in a `Vec` associated with specific mesh points. 674944a422c4SJames 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()`. 675044a422c4SJames Wright 675144a422c4SJames Wright `DMPlexVecGetClosureAtDepth()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 675244a422c4SJames Wright calling function. This is because `DMPlexVecGetClosureAtDepth()` is typically called in the inner loop of a `Vec` or `Mat` 675344a422c4SJames Wright assembly function, and a user may already have allocated storage for this operation. 675444a422c4SJames Wright 675544a422c4SJames Wright A typical use could be 675644a422c4SJames Wright .vb 675744a422c4SJames Wright values = NULL; 675844a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(dm, NULL, v, p, depth, &clSize, &values)); 675944a422c4SJames Wright for (cl = 0; cl < clSize; ++cl) { 676044a422c4SJames Wright <Compute on closure> 676144a422c4SJames Wright } 676244a422c4SJames Wright PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 676344a422c4SJames Wright .ve 676444a422c4SJames Wright or 676544a422c4SJames Wright .vb 676644a422c4SJames Wright PetscMalloc1(clMaxSize, &values); 676744a422c4SJames Wright for (p = pStart; p < pEnd; ++p) { 676844a422c4SJames Wright clSize = clMaxSize; 676944a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(dm, NULL, v, p, depth, &clSize, &values)); 677044a422c4SJames Wright for (cl = 0; cl < clSize; ++cl) { 677144a422c4SJames Wright <Compute on closure> 677244a422c4SJames Wright } 677344a422c4SJames Wright } 677444a422c4SJames Wright PetscFree(values); 677544a422c4SJames Wright .ve 677644a422c4SJames Wright 677744a422c4SJames Wright Fortran Notes: 677844a422c4SJames 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. 677944a422c4SJames Wright In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 678044a422c4SJames Wright 678144a422c4SJames Wright `values` must be declared with 678244a422c4SJames Wright .vb 678344a422c4SJames Wright PetscScalar,dimension(:),pointer :: values 678444a422c4SJames Wright .ve 678544a422c4SJames Wright and it will be allocated internally by PETSc to hold the values returned 678644a422c4SJames Wright 678744a422c4SJames Wright .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 678844a422c4SJames Wright @*/ 678944a422c4SJames Wright PetscErrorCode DMPlexVecGetClosureAtDepth(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6790d71ae5a4SJacob Faibussowitsch { 6791e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6792e5c487bfSMatthew G. Knepley PetscSection clSection; 6793e5c487bfSMatthew G. Knepley IS clPoints; 6794e5c487bfSMatthew G. Knepley PetscScalar *array; 6795e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6796e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6797c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6798c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6799e5c487bfSMatthew G. Knepley 6800e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6801e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 68029566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6803e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6804e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 68059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 68069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 68079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6808e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 68099566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 68103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6811e5c487bfSMatthew G. Knepley } 6812e5c487bfSMatthew G. Knepley /* Get points */ 681307218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6814c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6815c459fbc1SJed Brown PetscInt dof; 68169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6817c459fbc1SJed Brown clsize += dof; 6818c459fbc1SJed Brown } 68199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6820e5c487bfSMatthew G. Knepley /* Filter points */ 6821e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6822e5c487bfSMatthew G. Knepley PetscInt dep; 6823e5c487bfSMatthew G. Knepley 68249566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6825e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6826e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6827e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6828e5c487bfSMatthew G. Knepley ++Np; 6829e5c487bfSMatthew G. Knepley } 6830e5c487bfSMatthew G. Knepley /* Get array */ 6831e5c487bfSMatthew G. Knepley if (!values || !*values) { 6832e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6833e5c487bfSMatthew G. Knepley 6834e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 68359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6836e5c487bfSMatthew G. Knepley asize += dof; 6837e5c487bfSMatthew G. Knepley } 6838e5c487bfSMatthew G. Knepley if (!values) { 68399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6840e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 68413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6842e5c487bfSMatthew G. Knepley } 68439566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6844e5c487bfSMatthew G. Knepley } else { 6845e5c487bfSMatthew G. Knepley array = *values; 6846e5c487bfSMatthew G. Knepley } 68479566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6848e5c487bfSMatthew G. Knepley /* Get values */ 68499566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 68509566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6851e5c487bfSMatthew G. Knepley /* Cleanup points */ 68529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6853e5c487bfSMatthew G. Knepley /* Cleanup array */ 68549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6855e5c487bfSMatthew G. Knepley if (!*values) { 6856e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6857e5c487bfSMatthew G. Knepley *values = array; 6858e5c487bfSMatthew G. Knepley } else { 685963a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6860e5c487bfSMatthew G. Knepley *csize = size; 6861e5c487bfSMatthew G. Knepley } 68623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6863e5c487bfSMatthew G. Knepley } 6864e5c487bfSMatthew G. Knepley 6865552f7358SJed Brown /*@C 6866f13dfd9eSBarry Smith DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' obtained with `DMPlexVecGetClosure()` 6867552f7358SJed Brown 6868552f7358SJed Brown Not collective 6869552f7358SJed Brown 6870552f7358SJed Brown Input Parameters: 6871a1cb98faSBarry Smith + dm - The `DM` 687220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6873552f7358SJed Brown . v - The local vector 6874a1cb98faSBarry Smith . point - The point in the `DM` 687520f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6876f13dfd9eSBarry Smith - values - The array of values 6877552f7358SJed Brown 6878552f7358SJed Brown Level: intermediate 6879552f7358SJed Brown 6880a1cb98faSBarry Smith Note: 688120f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6882a1cb98faSBarry Smith 6883f13dfd9eSBarry Smith Fortran Note: 6884ce78bad3SBarry 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. 6885ce78bad3SBarry Smith In that case one may pass `PETSC_NULL_INTEGER` for `csize`. 6886a1cb98faSBarry Smith 68871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6888552f7358SJed Brown @*/ 6889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6890d71ae5a4SJacob Faibussowitsch { 6891552f7358SJed Brown PetscInt size = 0; 6892552f7358SJed Brown 6893552f7358SJed Brown PetscFunctionBegin; 6894552f7358SJed Brown /* Should work without recalculating size */ 68959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6896c9fdaa05SMatthew G. Knepley *values = NULL; 68973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6898552f7358SJed Brown } 6899552f7358SJed Brown 6900d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6901d71ae5a4SJacob Faibussowitsch { 69029371c9d4SSatish Balay *x += y; 69039371c9d4SSatish Balay } 6904d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6905d71ae5a4SJacob Faibussowitsch { 69069371c9d4SSatish Balay *x = y; 69079371c9d4SSatish Balay } 6908552f7358SJed Brown 6909d71ae5a4SJacob 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[]) 6910d71ae5a4SJacob Faibussowitsch { 6911552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6912552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6913552f7358SJed Brown PetscScalar *a; 6914552f7358SJed Brown PetscInt off, cind = 0, k; 6915552f7358SJed Brown 6916552f7358SJed Brown PetscFunctionBegin; 69179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 69189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6919552f7358SJed Brown a = &array[off]; 6920552f7358SJed Brown if (!cdof || setBC) { 692197e99dd9SToby Isaac if (clperm) { 69229371c9d4SSatish Balay if (perm) { 6923ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6924552f7358SJed Brown } else { 6925ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 69269371c9d4SSatish Balay } 69279371c9d4SSatish Balay } else { 69289371c9d4SSatish Balay if (perm) { 6929ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 69309371c9d4SSatish Balay } else { 6931ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 69329371c9d4SSatish Balay } 6933552f7358SJed Brown } 6934552f7358SJed Brown } else { 69359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 693697e99dd9SToby Isaac if (clperm) { 69379371c9d4SSatish Balay if (perm) { 69389371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 69399371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69409371c9d4SSatish Balay ++cind; 69419371c9d4SSatish Balay continue; 69429371c9d4SSatish Balay } 694397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6944552f7358SJed Brown } 6945552f7358SJed Brown } else { 6946552f7358SJed Brown for (k = 0; k < dof; ++k) { 69479371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69489371c9d4SSatish Balay ++cind; 69499371c9d4SSatish Balay continue; 69509371c9d4SSatish Balay } 695197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 695297e99dd9SToby Isaac } 695397e99dd9SToby Isaac } 695497e99dd9SToby Isaac } else { 695597e99dd9SToby Isaac if (perm) { 695697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 69579371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69589371c9d4SSatish Balay ++cind; 69599371c9d4SSatish Balay continue; 69609371c9d4SSatish Balay } 696197e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 696297e99dd9SToby Isaac } 696397e99dd9SToby Isaac } else { 696497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 69659371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69669371c9d4SSatish Balay ++cind; 69679371c9d4SSatish Balay continue; 69689371c9d4SSatish Balay } 696997e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 697097e99dd9SToby Isaac } 6971552f7358SJed Brown } 6972552f7358SJed Brown } 6973552f7358SJed Brown } 69743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6975552f7358SJed Brown } 6976552f7358SJed Brown 6977d71ae5a4SJacob 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[]) 6978d71ae5a4SJacob Faibussowitsch { 6979a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6980a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6981a5e93ea8SMatthew G. Knepley PetscScalar *a; 6982a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6983a5e93ea8SMatthew G. Knepley 6984a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 69859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 69869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6987a5e93ea8SMatthew G. Knepley a = &array[off]; 6988a5e93ea8SMatthew G. Knepley if (cdof) { 69899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 699097e99dd9SToby Isaac if (clperm) { 699197e99dd9SToby Isaac if (perm) { 6992a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6993a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 699497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 699597e99dd9SToby Isaac cind++; 6996a5e93ea8SMatthew G. Knepley } 6997a5e93ea8SMatthew G. Knepley } 6998a5e93ea8SMatthew G. Knepley } else { 6999a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 7000a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 700197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 700297e99dd9SToby Isaac cind++; 700397e99dd9SToby Isaac } 700497e99dd9SToby Isaac } 700597e99dd9SToby Isaac } 700697e99dd9SToby Isaac } else { 700797e99dd9SToby Isaac if (perm) { 700897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 700997e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 701097e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 701197e99dd9SToby Isaac cind++; 701297e99dd9SToby Isaac } 701397e99dd9SToby Isaac } 701497e99dd9SToby Isaac } else { 701597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 701697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 701797e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 701897e99dd9SToby Isaac cind++; 701997e99dd9SToby Isaac } 7020a5e93ea8SMatthew G. Knepley } 7021a5e93ea8SMatthew G. Knepley } 7022a5e93ea8SMatthew G. Knepley } 7023a5e93ea8SMatthew G. Knepley } 70243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7025a5e93ea8SMatthew G. Knepley } 7026a5e93ea8SMatthew G. Knepley 7027d71ae5a4SJacob 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[]) 7028d71ae5a4SJacob Faibussowitsch { 7029552f7358SJed Brown PetscScalar *a; 70301a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 70311a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 703297e99dd9SToby Isaac PetscInt cind = 0, b; 7033552f7358SJed Brown 7034552f7358SJed Brown PetscFunctionBegin; 70359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 70379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 70381a271a75SMatthew G. Knepley a = &array[foff]; 7039552f7358SJed Brown if (!fcdof || setBC) { 704097e99dd9SToby Isaac if (clperm) { 70419371c9d4SSatish Balay if (perm) { 7042ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7043552f7358SJed Brown } else { 7044ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 70459371c9d4SSatish Balay } 70469371c9d4SSatish Balay } else { 70479371c9d4SSatish Balay if (perm) { 7048ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 70499371c9d4SSatish Balay } else { 7050ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 70519371c9d4SSatish Balay } 7052552f7358SJed Brown } 7053552f7358SJed Brown } else { 70549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 705597e99dd9SToby Isaac if (clperm) { 705697e99dd9SToby Isaac if (perm) { 705797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70589371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70599371c9d4SSatish Balay ++cind; 70609371c9d4SSatish Balay continue; 70619371c9d4SSatish Balay } 706297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7063552f7358SJed Brown } 7064552f7358SJed Brown } else { 706597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70669371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70679371c9d4SSatish Balay ++cind; 70689371c9d4SSatish Balay continue; 70699371c9d4SSatish Balay } 707097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 707197e99dd9SToby Isaac } 707297e99dd9SToby Isaac } 707397e99dd9SToby Isaac } else { 707497e99dd9SToby Isaac if (perm) { 707597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70769371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70779371c9d4SSatish Balay ++cind; 70789371c9d4SSatish Balay continue; 70799371c9d4SSatish Balay } 708097e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 708197e99dd9SToby Isaac } 708297e99dd9SToby Isaac } else { 708397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 70849371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 70859371c9d4SSatish Balay ++cind; 70869371c9d4SSatish Balay continue; 70879371c9d4SSatish Balay } 708897e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7089552f7358SJed Brown } 7090552f7358SJed Brown } 7091552f7358SJed Brown } 7092552f7358SJed Brown } 70931a271a75SMatthew G. Knepley *offset += fdof; 70943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7095552f7358SJed Brown } 7096552f7358SJed Brown 7097d71ae5a4SJacob 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[]) 7098d71ae5a4SJacob Faibussowitsch { 7099a5e93ea8SMatthew G. Knepley PetscScalar *a; 71001a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 71011a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 71025da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 7103ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 7104a5e93ea8SMatthew G. Knepley 7105a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 71069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 71079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 71099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 71101a271a75SMatthew G. Knepley a = &array[foff]; 7111a5e93ea8SMatthew G. Knepley if (fcdof) { 7112ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 71139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 711497e99dd9SToby Isaac if (clperm) { 711597e99dd9SToby Isaac if (perm) { 7116ba322698SMatthew G. Knepley if (comps) { 7117ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7118ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71199371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71209371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71219371c9d4SSatish Balay ncSet = PETSC_TRUE; 71229371c9d4SSatish Balay } 71239371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71249371c9d4SSatish Balay ++cind; 71259371c9d4SSatish Balay fcSet = PETSC_TRUE; 71269371c9d4SSatish Balay } 7127ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7128ba322698SMatthew G. Knepley } 7129ba322698SMatthew G. Knepley } else { 713097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 713197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 713297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 7133a5e93ea8SMatthew G. Knepley ++cind; 7134a5e93ea8SMatthew G. Knepley } 7135a5e93ea8SMatthew G. Knepley } 7136ba322698SMatthew G. Knepley } 7137ba322698SMatthew G. Knepley } else { 7138ba322698SMatthew G. Knepley if (comps) { 7139ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7140ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71419371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71429371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71439371c9d4SSatish Balay ncSet = PETSC_TRUE; 71449371c9d4SSatish Balay } 71459371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71469371c9d4SSatish Balay ++cind; 71479371c9d4SSatish Balay fcSet = PETSC_TRUE; 71489371c9d4SSatish Balay } 7149ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 7150ba322698SMatthew G. Knepley } 7151a5e93ea8SMatthew G. Knepley } else { 715297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 715397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 715497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 715597e99dd9SToby Isaac ++cind; 715697e99dd9SToby Isaac } 715797e99dd9SToby Isaac } 715897e99dd9SToby Isaac } 7159ba322698SMatthew G. Knepley } 716097e99dd9SToby Isaac } else { 716197e99dd9SToby Isaac if (perm) { 7162ba322698SMatthew G. Knepley if (comps) { 7163ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7164ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71659371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71669371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71679371c9d4SSatish Balay ncSet = PETSC_TRUE; 71689371c9d4SSatish Balay } 71699371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71709371c9d4SSatish Balay ++cind; 71719371c9d4SSatish Balay fcSet = PETSC_TRUE; 71729371c9d4SSatish Balay } 7173ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 7174ba322698SMatthew G. Knepley } 7175ba322698SMatthew G. Knepley } else { 717697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 717797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 717897e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 717997e99dd9SToby Isaac ++cind; 718097e99dd9SToby Isaac } 718197e99dd9SToby Isaac } 7182ba322698SMatthew G. Knepley } 7183ba322698SMatthew G. Knepley } else { 7184ba322698SMatthew G. Knepley if (comps) { 7185ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 7186ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 71879371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 71889371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 71899371c9d4SSatish Balay ncSet = PETSC_TRUE; 71909371c9d4SSatish Balay } 71919371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 71929371c9d4SSatish Balay ++cind; 71939371c9d4SSatish Balay fcSet = PETSC_TRUE; 71949371c9d4SSatish Balay } 7195ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7196ba322698SMatthew G. Knepley } 719797e99dd9SToby Isaac } else { 719897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 719997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 720097e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 7201a5e93ea8SMatthew G. Knepley ++cind; 7202a5e93ea8SMatthew G. Knepley } 7203a5e93ea8SMatthew G. Knepley } 7204a5e93ea8SMatthew G. Knepley } 7205a5e93ea8SMatthew G. Knepley } 7206a5e93ea8SMatthew G. Knepley } 7207ba322698SMatthew G. Knepley } 72081a271a75SMatthew G. Knepley *offset += fdof; 72093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7210a5e93ea8SMatthew G. Knepley } 7211a5e93ea8SMatthew G. Knepley 7212d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7213d71ae5a4SJacob Faibussowitsch { 7214552f7358SJed Brown PetscScalar *array; 72151b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 72161b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 7217552f7358SJed Brown 72181b406b76SMatthew G. Knepley PetscFunctionBeginHot; 72199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 72209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 72219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 72229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 72239566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7224b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 7225b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 7226b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 7227b6ebb6e6SMatthew G. Knepley 72289371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 72299371c9d4SSatish Balay dof = 0; 72309371c9d4SSatish Balay continue; 72319371c9d4SSatish Balay } 72329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 7233b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 7234b6ebb6e6SMatthew G. Knepley { 7235b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7236b6ebb6e6SMatthew G. Knepley PetscScalar *a; 7237b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 7238b6ebb6e6SMatthew G. Knepley 72399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 72409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 7241b6ebb6e6SMatthew G. Knepley a = &array[coff]; 7242b6ebb6e6SMatthew G. Knepley if (!cdof) { 7243b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7244ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 7245b6ebb6e6SMatthew G. Knepley } else { 7246ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 7247b6ebb6e6SMatthew G. Knepley } 7248b6ebb6e6SMatthew G. Knepley } else { 72499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 7250b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7251b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 72529371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 72539371c9d4SSatish Balay ++cind; 72549371c9d4SSatish Balay continue; 72559371c9d4SSatish Balay } 7256b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 7257b6ebb6e6SMatthew G. Knepley } 7258b6ebb6e6SMatthew G. Knepley } else { 7259b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 72609371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 72619371c9d4SSatish Balay ++cind; 72629371c9d4SSatish Balay continue; 72639371c9d4SSatish Balay } 7264b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 7265b6ebb6e6SMatthew G. Knepley } 7266b6ebb6e6SMatthew G. Knepley } 7267b6ebb6e6SMatthew G. Knepley } 7268b6ebb6e6SMatthew G. Knepley } 7269b6ebb6e6SMatthew G. Knepley } 72709566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7272b6ebb6e6SMatthew G. Knepley } 72731b406b76SMatthew G. Knepley 72741b406b76SMatthew G. Knepley /*@C 727520f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 72761b406b76SMatthew G. Knepley 72771b406b76SMatthew G. Knepley Not collective 72781b406b76SMatthew G. Knepley 72791b406b76SMatthew G. Knepley Input Parameters: 7280a1cb98faSBarry Smith + dm - The `DM` 728120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 72821b406b76SMatthew G. Knepley . v - The local vector 728320f4b53cSBarry Smith . point - The point in the `DM` 72841b406b76SMatthew G. Knepley . values - The array of values 7285a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 7286a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 72871b406b76SMatthew G. Knepley 72881b406b76SMatthew G. Knepley Level: intermediate 72891b406b76SMatthew G. Knepley 7290f13dfd9eSBarry Smith Note: 7291f13dfd9eSBarry Smith Usually the input arrays were obtained with `DMPlexVecGetClosure()` 7292f13dfd9eSBarry Smith 72931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 72941b406b76SMatthew G. Knepley @*/ 7295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7296d71ae5a4SJacob Faibussowitsch { 72971b406b76SMatthew G. Knepley PetscSection clSection; 72981b406b76SMatthew G. Knepley IS clPoints; 72991b406b76SMatthew G. Knepley PetscScalar *array; 73001b406b76SMatthew G. Knepley PetscInt *points = NULL; 730127f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 7302c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 73031b406b76SMatthew G. Knepley 73041a271a75SMatthew G. Knepley PetscFunctionBeginHot; 73051b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 73069566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 73071a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 73081a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 73099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 73109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 73111b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 73129566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 73133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73141b406b76SMatthew G. Knepley } 73151a271a75SMatthew G. Knepley /* Get points */ 731607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7317c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 7318c459fbc1SJed Brown PetscInt dof; 73199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7320c459fbc1SJed Brown clsize += dof; 7321c459fbc1SJed Brown } 73229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 73231a271a75SMatthew G. Knepley /* Get array */ 73249566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 73251a271a75SMatthew G. Knepley /* Get values */ 7326ef90cfe2SMatthew G. Knepley if (numFields > 0) { 732797e99dd9SToby Isaac PetscInt offset = 0, f; 7328552f7358SJed Brown for (f = 0; f < numFields; ++f) { 732997e99dd9SToby Isaac const PetscInt **perms = NULL; 733097e99dd9SToby Isaac const PetscScalar **flips = NULL; 733197e99dd9SToby Isaac 73329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7333552f7358SJed Brown switch (mode) { 7334552f7358SJed Brown case INSERT_VALUES: 733597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 733697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 733797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 733897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73393ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 73409371c9d4SSatish Balay } 73419371c9d4SSatish Balay break; 7342552f7358SJed Brown case INSERT_ALL_VALUES: 734397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 734497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 734597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 734697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73473ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 73489371c9d4SSatish Balay } 73499371c9d4SSatish Balay break; 7350a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 735197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 735297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 735397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 735497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73553ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 73569371c9d4SSatish Balay } 73579371c9d4SSatish Balay break; 7358552f7358SJed Brown case ADD_VALUES: 735997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 736097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 736197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 736297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73633ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 73649371c9d4SSatish Balay } 73659371c9d4SSatish Balay break; 7366552f7358SJed Brown case ADD_ALL_VALUES: 736797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 736897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 736997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 737097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73713ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 73729371c9d4SSatish Balay } 73739371c9d4SSatish Balay break; 7374304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 737597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 737697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 737797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 737897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73793ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 73809371c9d4SSatish Balay } 73819371c9d4SSatish Balay break; 7382d71ae5a4SJacob Faibussowitsch default: 7383d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7384552f7358SJed Brown } 73859566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 73861a271a75SMatthew G. Knepley } 7387552f7358SJed Brown } else { 73881a271a75SMatthew G. Knepley PetscInt dof, off; 738997e99dd9SToby Isaac const PetscInt **perms = NULL; 739097e99dd9SToby Isaac const PetscScalar **flips = NULL; 73911a271a75SMatthew G. Knepley 73929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7393552f7358SJed Brown switch (mode) { 7394552f7358SJed Brown case INSERT_VALUES: 739597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 739697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 739797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 739897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 73999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74003ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 74019371c9d4SSatish Balay } 74029371c9d4SSatish Balay break; 7403552f7358SJed Brown case INSERT_ALL_VALUES: 740497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 740597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 740697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 740797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74093ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 74109371c9d4SSatish Balay } 74119371c9d4SSatish Balay break; 7412a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 741397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 741497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 741597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 741697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74183ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 74199371c9d4SSatish Balay } 74209371c9d4SSatish Balay break; 7421552f7358SJed Brown case ADD_VALUES: 742297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 742397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 742497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 742597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74273ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 74289371c9d4SSatish Balay } 74299371c9d4SSatish Balay break; 7430552f7358SJed Brown case ADD_ALL_VALUES: 743197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 743297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 743397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 743497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74363ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 74379371c9d4SSatish Balay } 74389371c9d4SSatish Balay break; 7439304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 744097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 744197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 744297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 744397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 74449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74453ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 74469371c9d4SSatish Balay } 74479371c9d4SSatish Balay break; 7448d71ae5a4SJacob Faibussowitsch default: 7449d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7450552f7358SJed Brown } 74519566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7452552f7358SJed Brown } 74531a271a75SMatthew G. Knepley /* Cleanup points */ 74549566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 74551a271a75SMatthew G. Knepley /* Cleanup array */ 74569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 74573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7458552f7358SJed Brown } 7459552f7358SJed Brown 74605f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7461d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7462d71ae5a4SJacob Faibussowitsch { 74635f790a90SMatthew G. Knepley PetscFunctionBegin; 746411cc89d2SBarry Smith *contains = PETSC_TRUE; 74655f790a90SMatthew G. Knepley if (label) { 7466d6177c40SToby Isaac PetscInt fdof; 74675f790a90SMatthew G. Knepley 746811cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 746911cc89d2SBarry Smith if (!*contains) { 74709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74715f790a90SMatthew G. Knepley *offset += fdof; 74723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74735f790a90SMatthew G. Knepley } 74745f790a90SMatthew G. Knepley } 74753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74765f790a90SMatthew G. Knepley } 74775f790a90SMatthew G. Knepley 747897529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7479d71ae5a4SJacob 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) 7480d71ae5a4SJacob Faibussowitsch { 7481e07394fbSMatthew G. Knepley PetscSection clSection; 7482e07394fbSMatthew G. Knepley IS clPoints; 7483e07394fbSMatthew G. Knepley PetscScalar *array; 7484e07394fbSMatthew G. Knepley PetscInt *points = NULL; 748597529cf3SJed Brown const PetscInt *clp; 7486e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 748797e99dd9SToby Isaac PetscInt offset = 0, f; 7488e07394fbSMatthew G. Knepley 7489e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7490e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 74919566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7492e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7493e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 74949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7495e07394fbSMatthew G. Knepley /* Get points */ 749607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7497e07394fbSMatthew G. Knepley /* Get array */ 74989566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7499e07394fbSMatthew G. Knepley /* Get values */ 7500e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 750197e99dd9SToby Isaac const PetscInt **perms = NULL; 750297e99dd9SToby Isaac const PetscScalar **flips = NULL; 750311cc89d2SBarry Smith PetscBool contains; 750497e99dd9SToby Isaac 7505e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7506e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7507e07394fbSMatthew G. Knepley PetscInt fdof; 75089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7509e07394fbSMatthew G. Knepley offset += fdof; 7510e07394fbSMatthew G. Knepley } 7511e07394fbSMatthew G. Knepley continue; 7512e07394fbSMatthew G. Knepley } 75139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7514e07394fbSMatthew G. Knepley switch (mode) { 7515e07394fbSMatthew G. Knepley case INSERT_VALUES: 751697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 751797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 751897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 751997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 752011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 752111cc89d2SBarry Smith if (!contains) continue; 75229566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 75239371c9d4SSatish Balay } 75249371c9d4SSatish Balay break; 7525e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 752697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 752797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 752897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 752997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 753011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 753111cc89d2SBarry Smith if (!contains) continue; 75329566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 75339371c9d4SSatish Balay } 75349371c9d4SSatish Balay break; 7535e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 753697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 753797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 753897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 753997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 754011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 754111cc89d2SBarry Smith if (!contains) continue; 75429566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 75439371c9d4SSatish Balay } 75449371c9d4SSatish Balay break; 7545e07394fbSMatthew G. Knepley case ADD_VALUES: 754697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 754797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 754897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 754997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 755011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 755111cc89d2SBarry Smith if (!contains) continue; 75529566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 75539371c9d4SSatish Balay } 75549371c9d4SSatish Balay break; 7555e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 755697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 755797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 755897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 755997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 756011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 756111cc89d2SBarry Smith if (!contains) continue; 75629566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 75639371c9d4SSatish Balay } 75649371c9d4SSatish Balay break; 7565d71ae5a4SJacob Faibussowitsch default: 7566d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7567e07394fbSMatthew G. Knepley } 75689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7569e07394fbSMatthew G. Knepley } 7570e07394fbSMatthew G. Knepley /* Cleanup points */ 75719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7572e07394fbSMatthew G. Knepley /* Cleanup array */ 75739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 75743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7575e07394fbSMatthew G. Knepley } 7576e07394fbSMatthew G. Knepley 7577d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7578d71ae5a4SJacob Faibussowitsch { 7579552f7358SJed Brown PetscMPIInt rank; 7580552f7358SJed Brown PetscInt i, j; 7581552f7358SJed Brown 7582552f7358SJed Brown PetscFunctionBegin; 75839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 758463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 758563a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 758663a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7587b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 75883ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7589b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 75909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7591b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7592519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 75939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7594552f7358SJed Brown #else 75959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7596552f7358SJed Brown #endif 7597552f7358SJed Brown } 75989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7599552f7358SJed Brown } 76003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7601552f7358SJed Brown } 7602552f7358SJed Brown 760305586334SMatthew G. Knepley /* 760405586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 760505586334SMatthew G. Knepley 760605586334SMatthew G. Knepley Input Parameters: 760705586334SMatthew G. Knepley + section - The section for this data layout 760836fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 760905586334SMatthew G. Knepley . point - The point contributing dofs with these indices 761005586334SMatthew G. Knepley . off - The global offset of this point 761105586334SMatthew G. Knepley . loff - The local offset of each field 7612a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 761305586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 761405586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 761505586334SMatthew G. Knepley 761605586334SMatthew G. Knepley Output Parameter: 761705586334SMatthew G. Knepley . indices - Indices for dofs on this point 761805586334SMatthew G. Knepley 761905586334SMatthew G. Knepley Level: developer 762005586334SMatthew G. Knepley 762105586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 762205586334SMatthew G. Knepley */ 7623d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7624d71ae5a4SJacob Faibussowitsch { 7625e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7626552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7627552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7628552f7358SJed Brown PetscInt cind = 0, k; 7629552f7358SJed Brown 7630552f7358SJed Brown PetscFunctionBegin; 763108401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 76329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 76339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7634552f7358SJed Brown if (!cdof || setBC) { 763505586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 763605586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 763705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 763805586334SMatthew G. Knepley 763905586334SMatthew G. Knepley indices[ind] = off + k; 7640552f7358SJed Brown } 7641552f7358SJed Brown } else { 76429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 76434acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 764405586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 764505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 764605586334SMatthew G. Knepley 76474acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 76484acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 764905586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 76504acb8e1eSToby Isaac ++cind; 76514acb8e1eSToby Isaac } else { 765236fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7653552f7358SJed Brown } 7654552f7358SJed Brown } 7655552f7358SJed Brown } 7656e6ccafaeSMatthew G Knepley *loff += dof; 76573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7658552f7358SJed Brown } 7659552f7358SJed Brown 76607e29afd2SMatthew G. Knepley /* 766136fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 76627e29afd2SMatthew G. Knepley 766336fa2b79SJed Brown Input Parameters: 766436fa2b79SJed Brown + section - a section (global or local) 766520f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 766636fa2b79SJed Brown . point - point within section 766736fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 766836fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 766936fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 767036fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 767136fa2b79SJed Brown . permsoff - offset 767236fa2b79SJed Brown - indperm - index permutation 767336fa2b79SJed Brown 767436fa2b79SJed Brown Output Parameter: 767536fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 767636fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 767736fa2b79SJed Brown 767836fa2b79SJed Brown Notes: 767936fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 768036fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 768136fa2b79SJed Brown in the local vector. 768236fa2b79SJed Brown 768336fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 768436fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 768536fa2b79SJed Brown 768636fa2b79SJed Brown Developer Note: 768736fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 768836fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 768936fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 769036fa2b79SJed Brown 769136fa2b79SJed Brown Example: 769236fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 769336fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 769436fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 769536fa2b79SJed 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. 769636fa2b79SJed Brown 769736fa2b79SJed Brown Level: developer 76987e29afd2SMatthew G. Knepley */ 7699d71ae5a4SJacob 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[]) 7700d71ae5a4SJacob Faibussowitsch { 7701552f7358SJed Brown PetscInt numFields, foff, f; 7702552f7358SJed Brown 7703552f7358SJed Brown PetscFunctionBegin; 770408401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 77059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7706552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 77074acb8e1eSToby Isaac PetscInt fdof, cfdof; 7708552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 77094acb8e1eSToby Isaac PetscInt cind = 0, b; 77104acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7711552f7358SJed Brown 77129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 77139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7714552f7358SJed Brown if (!cfdof || setBC) { 771505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 771605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 771705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 771805586334SMatthew G. Knepley 771905586334SMatthew G. Knepley indices[ind] = off + foff + b; 772005586334SMatthew G. Knepley } 7721552f7358SJed Brown } else { 77229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 772305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 772405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 772505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 772605586334SMatthew G. Knepley 77274acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 772805586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7729552f7358SJed Brown ++cind; 7730552f7358SJed Brown } else { 773136fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7732552f7358SJed Brown } 7733552f7358SJed Brown } 7734552f7358SJed Brown } 773536fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7736552f7358SJed Brown foffs[f] += fdof; 7737552f7358SJed Brown } 77383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7739552f7358SJed Brown } 7740552f7358SJed Brown 77417e29afd2SMatthew G. Knepley /* 77427e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 77437e29afd2SMatthew G. Knepley 77447e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7745645102dcSJed Brown 7746645102dcSJed Brown Notes: 7747645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7748645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 77497e29afd2SMatthew G. Knepley */ 7750d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7751d71ae5a4SJacob Faibussowitsch { 77527e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 77537e29afd2SMatthew G. Knepley 77547e29afd2SMatthew G. Knepley PetscFunctionBegin; 77559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 77567e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 77577e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 77587e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 77597e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 77607e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 77617e29afd2SMatthew G. Knepley 77629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 77639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 77649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7765645102dcSJed Brown if (!cfdof) { 776605586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 776705586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 776805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 776905586334SMatthew G. Knepley 777005586334SMatthew G. Knepley indices[ind] = foff + b; 777105586334SMatthew G. Knepley } 77727e29afd2SMatthew G. Knepley } else { 77739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 777405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 777505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 777605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 777705586334SMatthew G. Knepley 77787e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 777905586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 77807e29afd2SMatthew G. Knepley ++cind; 77817e29afd2SMatthew G. Knepley } else { 778205586334SMatthew G. Knepley indices[ind] = foff + b - cind; 77837e29afd2SMatthew G. Knepley } 77847e29afd2SMatthew G. Knepley } 77857e29afd2SMatthew G. Knepley } 77867e29afd2SMatthew G. Knepley foffs[f] += fdof; 77877e29afd2SMatthew G. Knepley } 77883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77897e29afd2SMatthew G. Knepley } 77907e29afd2SMatthew G. Knepley 7791c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms) 7792c789d87fSToby Isaac { 7793c789d87fSToby Isaac PetscInt numFields, sStart, sEnd, cStart, cEnd; 7794c789d87fSToby Isaac 7795c789d87fSToby Isaac PetscFunctionBegin; 7796c789d87fSToby Isaac PetscCall(PetscSectionGetNumFields(section, &numFields)); 7797c789d87fSToby Isaac PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7798c789d87fSToby Isaac PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7799c789d87fSToby Isaac for (PetscInt p = 0; p < nPoints; p++) { 7800c789d87fSToby Isaac PetscInt b = pnts[2 * p]; 7801c789d87fSToby Isaac PetscInt bSecDof = 0, bOff; 7802c789d87fSToby Isaac PetscInt cSecDof = 0; 7803c789d87fSToby Isaac PetscSection indices_section; 7804c789d87fSToby Isaac 7805c789d87fSToby Isaac if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7806c789d87fSToby Isaac if (!bSecDof) continue; 7807c789d87fSToby Isaac if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof)); 7808c789d87fSToby Isaac indices_section = cSecDof > 0 ? cSec : section; 7809c789d87fSToby Isaac if (numFields) { 7810c789d87fSToby Isaac PetscInt fStart[32], fEnd[32]; 7811c789d87fSToby Isaac 7812c789d87fSToby Isaac fStart[0] = 0; 7813c789d87fSToby Isaac fEnd[0] = 0; 7814c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7815c789d87fSToby Isaac PetscInt fDof = 0; 7816c789d87fSToby Isaac 7817c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof)); 7818c789d87fSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7819c789d87fSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7820c789d87fSToby Isaac } 7821c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7822c789d87fSToby Isaac // only apply permutations on one side 7823c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices)); 7824c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7825ac530a7eSPierre Jolivet for (PetscInt i = fStart[f]; i < fEnd[f]; i++) indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7826c789d87fSToby Isaac } 7827c789d87fSToby Isaac } else { 7828c789d87fSToby Isaac PetscInt bEnd = 0; 7829c789d87fSToby Isaac 7830c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7831c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices)); 7832c789d87fSToby Isaac 7833c789d87fSToby Isaac for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7834c789d87fSToby Isaac } 7835c789d87fSToby Isaac } 7836c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7837c789d87fSToby Isaac } 7838c789d87fSToby Isaac 7839c789d87fSToby 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[]) 7840d71ae5a4SJacob Faibussowitsch { 7841d3d1a6afSToby Isaac Mat cMat; 7842d3d1a6afSToby Isaac PetscSection aSec, cSec; 7843d3d1a6afSToby Isaac IS aIS; 7844d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7845a19ea1e9SMatthew G. Knepley PetscInt sStart = -1, sEnd = -1; 7846a19ea1e9SMatthew G. Knepley PetscInt cStart = -1, cEnd = -1; 7847d3d1a6afSToby Isaac const PetscInt *anchors; 7848e969e7a5SJose E. Roman PetscInt numFields, p; 7849d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7850c789d87fSToby Isaac PetscInt *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices; 7851c789d87fSToby Isaac PetscInt oldOffsets[32]; 7852d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7853c789d87fSToby Isaac PetscInt oldOffsetsCopy[32]; 7854c789d87fSToby Isaac PetscInt newOffsetsCopy[32]; 7855c789d87fSToby Isaac PetscScalar *modMat = NULL; 7856d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7857d3d1a6afSToby Isaac 7858d3d1a6afSToby Isaac PetscFunctionBegin; 7859d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7860d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 78619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7862d3d1a6afSToby Isaac 78639566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7864d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7865d3d1a6afSToby Isaac if (aSec) { 78669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 7867c789d87fSToby Isaac PetscCall(PetscArrayzero(oldOffsets, 32)); 78689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 78699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7870a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7871d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7872d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7873d3d1a6afSToby Isaac * into the global matrix anyway) */ 7874d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7875d3d1a6afSToby Isaac PetscInt b = points[p]; 7876a19ea1e9SMatthew G. Knepley PetscInt bDof = 0, bSecDof = 0; 7877d3d1a6afSToby Isaac 7878a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7879ad540459SPierre Jolivet if (!bSecDof) continue; 7880c789d87fSToby Isaac 7881c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7882c789d87fSToby Isaac PetscInt fDof = 0; 7883c789d87fSToby Isaac 7884c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7885c789d87fSToby Isaac oldOffsets[f + 1] += fDof; 7886c789d87fSToby Isaac } 788748a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7888d3d1a6afSToby Isaac if (bDof) { 7889d3d1a6afSToby Isaac /* this point is constrained */ 7890d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7891d3d1a6afSToby Isaac PetscInt bOff, q; 7892d3d1a6afSToby Isaac 78939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7894d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7895d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7896a19ea1e9SMatthew G. Knepley PetscInt aDof = 0; 7897d3d1a6afSToby Isaac 7898a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7899c789d87fSToby Isaac if (aDof) { 7900c789d87fSToby Isaac anyConstrained = PETSC_TRUE; 7901c789d87fSToby Isaac newNumPoints += 1; 7902c789d87fSToby Isaac } 7903d3d1a6afSToby Isaac newNumIndices += aDof; 7904e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7905a19ea1e9SMatthew G. Knepley PetscInt fDof = 0; 7906d3d1a6afSToby Isaac 7907a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7908d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7909d3d1a6afSToby Isaac } 7910d3d1a6afSToby Isaac } 79119371c9d4SSatish Balay } else { 7912d3d1a6afSToby Isaac /* this point is not constrained */ 7913d3d1a6afSToby Isaac newNumPoints++; 79144b2f2278SToby Isaac newNumIndices += bSecDof; 7915e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7916d3d1a6afSToby Isaac PetscInt fDof; 7917d3d1a6afSToby Isaac 79189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7919d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7920d3d1a6afSToby Isaac } 7921d3d1a6afSToby Isaac } 7922d3d1a6afSToby Isaac } 7923d3d1a6afSToby Isaac } 7924d3d1a6afSToby Isaac if (!anyConstrained) { 792572b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 792672b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 792772b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 7928c789d87fSToby Isaac if (outMat) *outMat = NULL; 79299566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 79303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7931d3d1a6afSToby Isaac } 7932d3d1a6afSToby Isaac 79336ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 79346ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 79356ecaa68aSToby Isaac 7936e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7937e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f]; 7938d3d1a6afSToby Isaac 7939c789d87fSToby Isaac if (!outPoints && !outMat) { 79406ecaa68aSToby Isaac if (offsets) { 7941e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 79426ecaa68aSToby Isaac } 79439566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 79443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79456ecaa68aSToby Isaac } 79466ecaa68aSToby Isaac 79471dca8a05SBarry 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); 7948c789d87fSToby 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); 7949d3d1a6afSToby Isaac 79509566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7951a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7952d3d1a6afSToby Isaac 79536ecaa68aSToby Isaac /* output arrays */ 79549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 7955c789d87fSToby Isaac PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints)); 79566ecaa68aSToby Isaac 7957c789d87fSToby Isaac // get the new Points 7958c789d87fSToby Isaac for (PetscInt p = 0, newP = 0; p < numPoints; p++) { 7959d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7960c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7961d3d1a6afSToby Isaac 7962a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7963ad540459SPierre Jolivet if (!bSecDof) continue; 796448a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7965d3d1a6afSToby Isaac if (bDof) { 79669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7967c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++) { 7968a19ea1e9SMatthew G. Knepley PetscInt a = anchors[bOff + q], aDof = 0; 7969d3d1a6afSToby Isaac 7970a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7971c789d87fSToby Isaac if (aDof) { 7972c789d87fSToby Isaac newPoints[2 * newP] = a; 7973c789d87fSToby Isaac newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation 7974d3d1a6afSToby Isaac newP++; 7975d3d1a6afSToby Isaac } 7976d3d1a6afSToby Isaac } 7977d3d1a6afSToby Isaac } else { 7978d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7979c789d87fSToby Isaac newPoints[2 * newP + 1] = points[2 * p + 1]; 7980d3d1a6afSToby Isaac newP++; 7981d3d1a6afSToby Isaac } 7982d3d1a6afSToby Isaac } 7983d3d1a6afSToby Isaac 7984c789d87fSToby Isaac if (outMat) { 7985c789d87fSToby Isaac PetscScalar *tmpMat; 7986c789d87fSToby Isaac PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32)); 7987c789d87fSToby Isaac PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32)); 7988c789d87fSToby Isaac 7989c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices)); 7990c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7991c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7992c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7993c789d87fSToby Isaac 7994c789d87fSToby Isaac for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1; 7995c789d87fSToby Isaac for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1; 7996c789d87fSToby Isaac 7997c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms)); 7998c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL)); 7999c789d87fSToby Isaac 8000c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 8001c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 8002c789d87fSToby Isaac PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices)); 8003c789d87fSToby Isaac // for each field, insert the anchor modification into modMat 8004c789d87fSToby Isaac for (PetscInt f = 0; f < PetscMax(1, numFields); f++) { 8005c789d87fSToby Isaac PetscInt fStart = oldOffsets[f]; 8006c789d87fSToby Isaac PetscInt fNewStart = newOffsets[f]; 8007e60de12fSPierre Jolivet for (PetscInt p = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) { 8008c789d87fSToby Isaac PetscInt b = points[2 * p]; 8009c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 8010c789d87fSToby Isaac 8011c789d87fSToby Isaac if (b >= sStart && b < sEnd) { 8012d3d1a6afSToby Isaac if (numFields) { 8013c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof)); 80149371c9d4SSatish Balay } else { 8015c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 8016d3d1a6afSToby Isaac } 8017d3d1a6afSToby Isaac } 8018c789d87fSToby Isaac if (!bSecDof) continue; 8019c789d87fSToby Isaac if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 8020c789d87fSToby Isaac if (bDof) { 8021c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 8022e60de12fSPierre Jolivet for (PetscInt q = 0; q < bDof; q++) { 8023c789d87fSToby Isaac PetscInt a = anchors[bOff + q], aDof = 0; 8024d3d1a6afSToby Isaac 8025c789d87fSToby Isaac if (a >= sStart && a < sEnd) { 8026d3d1a6afSToby Isaac if (numFields) { 8027c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 8028c789d87fSToby Isaac } else { 8029c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, a, &aDof)); 8030d3d1a6afSToby Isaac } 8031d3d1a6afSToby Isaac } 8032c789d87fSToby Isaac if (aDof) { 8033c789d87fSToby Isaac PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat)); 8034c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) { 8035c789d87fSToby Isaac for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e]; 8036c789d87fSToby Isaac } 8037c789d87fSToby Isaac } 8038c789d87fSToby Isaac oNew += aDof; 8039c789d87fSToby Isaac } 80409371c9d4SSatish Balay } else { 8041c789d87fSToby Isaac // Insert the identity matrix in this block 8042c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1; 8043c789d87fSToby Isaac oNew += bSecDof; 8044d3d1a6afSToby Isaac } 8045c789d87fSToby Isaac o += bSecDof; 8046d3d1a6afSToby Isaac } 8047d3d1a6afSToby Isaac } 8048d3d1a6afSToby Isaac 8049c789d87fSToby Isaac *outMat = modMat; 80506ecaa68aSToby Isaac 8051c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 8052c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 8053c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 8054c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 8055c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices)); 8056d3d1a6afSToby Isaac } 80579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 8058d3d1a6afSToby Isaac 8059d3d1a6afSToby Isaac /* output */ 80606ecaa68aSToby Isaac if (outPoints) { 8061d3d1a6afSToby Isaac *outPoints = newPoints; 80629371c9d4SSatish Balay } else { 80639566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 80646ecaa68aSToby Isaac } 8065e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 80663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8067d3d1a6afSToby Isaac } 8068d3d1a6afSToby Isaac 8069c789d87fSToby 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) 8070c789d87fSToby Isaac { 8071c789d87fSToby Isaac PetscScalar *modMat = NULL; 8072c789d87fSToby Isaac PetscInt newNumIndices = -1; 80737cd05799SMatthew G. Knepley 8074c789d87fSToby Isaac PetscFunctionBegin; 8075c789d87fSToby 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. 8076c789d87fSToby Isaac modMat is that matrix C */ 8077c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL)); 8078c789d87fSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 8079c789d87fSToby Isaac if (modMat) { 8080c789d87fSToby Isaac const PetscScalar *newValues = values; 80817cd05799SMatthew G. Knepley 8082c789d87fSToby Isaac if (multiplyRight) { 8083c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 80846497c311SBarry Smith PetscBLASInt M, N, K; 8085c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 80867cd05799SMatthew G. Knepley 8087c789d87fSToby 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); 80887cd05799SMatthew G. Knepley 80896497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &M)); 80906497c311SBarry Smith PetscCall(PetscBLASIntCast(numRows, &N)); 80916497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 8092c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues)); 8093c789d87fSToby Isaac // row-major to column-major conversion, right multiplication becomes left multiplication 8094c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M)); 8095c789d87fSToby Isaac numCols = newNumIndices; 8096c789d87fSToby Isaac newValues = newNewValues; 8097c789d87fSToby Isaac } 8098a1cb98faSBarry Smith 8099c789d87fSToby Isaac if (multiplyLeft) { 8100c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 81016497c311SBarry Smith PetscBLASInt M, N, K; 8102c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 81037cd05799SMatthew G. Knepley 8104c789d87fSToby 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); 8105c789d87fSToby Isaac 81066497c311SBarry Smith PetscCall(PetscBLASIntCast(numCols, &M)); 81076497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &N)); 81086497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 8109c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues)); 8110c789d87fSToby Isaac // row-major to column-major conversion, left multiplication becomes right multiplication 8111c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M)); 8112c789d87fSToby Isaac if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues)); 8113c789d87fSToby Isaac newValues = newNewValues; 8114c789d87fSToby Isaac } 8115c789d87fSToby Isaac *outValues = (PetscScalar *)newValues; 8116c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 8117c789d87fSToby Isaac } 8118c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8119c789d87fSToby Isaac } 8120c789d87fSToby Isaac 8121c789d87fSToby 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) 8122c789d87fSToby Isaac { 8123c789d87fSToby Isaac PetscFunctionBegin; 8124c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft)); 8125c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8126c789d87fSToby Isaac } 8127c789d87fSToby Isaac 8128c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize) 8129c789d87fSToby Isaac { 8130c789d87fSToby Isaac /* Closure ordering */ 8131c789d87fSToby Isaac PetscSection clSection; 8132c789d87fSToby Isaac IS clPoints; 8133c789d87fSToby Isaac const PetscInt *clp; 8134c789d87fSToby Isaac PetscInt *points; 8135c789d87fSToby Isaac PetscInt Ncl, Ni = 0; 8136c789d87fSToby Isaac 8137c789d87fSToby Isaac PetscFunctionBeginHot; 8138c789d87fSToby Isaac PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 8139c789d87fSToby Isaac for (PetscInt p = 0; p < Ncl * 2; p += 2) { 8140c789d87fSToby Isaac PetscInt dof; 8141c789d87fSToby Isaac 8142c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, points[p], &dof)); 8143c789d87fSToby Isaac Ni += dof; 8144c789d87fSToby Isaac } 8145c789d87fSToby Isaac PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 8146c789d87fSToby Isaac *closureSize = Ni; 8147c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 8148c789d87fSToby Isaac } 8149c789d87fSToby Isaac 8150c789d87fSToby 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) 8151d71ae5a4SJacob Faibussowitsch { 815271f0bbf9SMatthew G. Knepley /* Closure ordering */ 81537773e69fSMatthew G. Knepley PetscSection clSection; 81547773e69fSMatthew G. Knepley IS clPoints; 815571f0bbf9SMatthew G. Knepley const PetscInt *clp; 815671f0bbf9SMatthew G. Knepley PetscInt *points; 815771f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 815871f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 81594acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 816071f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 816171f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 816271f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 816371f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 816471f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 816571f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 816671f0bbf9SMatthew G. Knepley 816771f0bbf9SMatthew G. Knepley PetscInt *idx; 816871f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 816971f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 81707caea556SToby Isaac PetscInt idxStart, idxEnd; 8171c789d87fSToby Isaac PetscInt nRows, nCols; 81727773e69fSMatthew G. Knepley 817371f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 81747773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81757773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 817636fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 8177c789d87fSToby Isaac PetscAssertPointer(numRows, 6); 8178c789d87fSToby Isaac PetscAssertPointer(numCols, 7); 8179c789d87fSToby Isaac if (indices) PetscAssertPointer(indices, 8); 8180c789d87fSToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 9); 8181c789d87fSToby Isaac if (values) PetscAssertPointer(values, 10); 81829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 818363a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 81849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 818571f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 818607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 8187c459fbc1SJed Brown if (useClPerm) { 8188c459fbc1SJed Brown PetscInt depth, clsize; 81899566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 8190c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 8191c459fbc1SJed Brown PetscInt dof; 81929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 8193c459fbc1SJed Brown clsize += dof; 8194c459fbc1SJed Brown } 81959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 8196c459fbc1SJed Brown } 819771f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 819871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 81997773e69fSMatthew G. Knepley PetscInt dof, fdof; 82007773e69fSMatthew G. Knepley 82019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 82027773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 82039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 82047773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 82057773e69fSMatthew G. Knepley } 820671f0bbf9SMatthew G. Knepley Ni += dof; 82077773e69fSMatthew G. Knepley } 8208c789d87fSToby Isaac if (*numRows == -1) *numRows = Ni; 8209c789d87fSToby Isaac if (*numCols == -1) *numCols = Ni; 8210c789d87fSToby Isaac nRows = *numRows; 8211c789d87fSToby Isaac nCols = *numCols; 82127773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 82131dca8a05SBarry 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); 821471f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 8215c789d87fSToby Isaac if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols); 8216c789d87fSToby Isaac if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows); 821771f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82189566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 82199566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 822071f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 822171f0bbf9SMatthew G. Knepley if (values && flips[f]) { 822271f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 82236ecaa68aSToby Isaac 822471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 822571f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 822671f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 822771f0bbf9SMatthew G. Knepley 82289566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 82299566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 823071f0bbf9SMatthew G. Knepley if (flip) { 823171f0bbf9SMatthew G. Knepley PetscInt i, j, k; 823271f0bbf9SMatthew G. Knepley 823371f0bbf9SMatthew G. Knepley if (!valCopy) { 82349566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 823571f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 823671f0bbf9SMatthew G. Knepley *values = valCopy; 823771f0bbf9SMatthew G. Knepley } 823871f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 823971f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 824071f0bbf9SMatthew G. Knepley 8241c789d87fSToby Isaac if (multiplyRight) { 8242ac530a7eSPierre Jolivet for (k = 0; k < nRows; ++k) valCopy[Ni * k + (foffset + i)] *= fval; 8243c789d87fSToby Isaac } 8244c789d87fSToby Isaac if (multiplyLeft) { 8245ac530a7eSPierre Jolivet for (k = 0; k < nCols; ++k) valCopy[nCols * (foffset + i) + k] *= fval; 82466ecaa68aSToby Isaac } 82476ecaa68aSToby Isaac } 824871f0bbf9SMatthew G. Knepley } 824971f0bbf9SMatthew G. Knepley foffset += fdof; 825071f0bbf9SMatthew G. Knepley } 825171f0bbf9SMatthew G. Knepley } 825271f0bbf9SMatthew G. Knepley } 825371f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 8254c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft)); 825571f0bbf9SMatthew G. Knepley if (NclC) { 825663bfac88SBarry Smith if (multiplyRight) *numCols = NiC; 825763bfac88SBarry Smith if (multiplyLeft) *numRows = NiC; 82589566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 825971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82609566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 82619566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 826271f0bbf9SMatthew G. Knepley } 826371f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 82649566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 82659566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 826671f0bbf9SMatthew G. Knepley } 82679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 826871f0bbf9SMatthew G. Knepley Ncl = NclC; 826971f0bbf9SMatthew G. Knepley Ni = NiC; 827071f0bbf9SMatthew G. Knepley points = pointsC; 827171f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 827271f0bbf9SMatthew G. Knepley } 827371f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 82749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 82757caea556SToby Isaac PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd)); 827671f0bbf9SMatthew G. Knepley if (Nf) { 827771f0bbf9SMatthew G. Knepley PetscInt idxOff; 827871f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 827971f0bbf9SMatthew G. Knepley 82809371c9d4SSatish Balay if (outOffsets) { 82819371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 82829371c9d4SSatish Balay } 82839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 828471f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 828571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 828671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 828771f0bbf9SMatthew G. Knepley 82889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 82897773e69fSMatthew G. Knepley } 82907773e69fSMatthew G. Knepley } else { 829171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 829271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 829371f0bbf9SMatthew G. Knepley 82947caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 82959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 829671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 829771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 829871f0bbf9SMatthew G. Knepley * global section. */ 82999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 830071f0bbf9SMatthew G. Knepley } 830171f0bbf9SMatthew G. Knepley } 830271f0bbf9SMatthew G. Knepley } else { 830371f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 830471f0bbf9SMatthew G. Knepley 830571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 830671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 83074acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 83084acb8e1eSToby Isaac 83097caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 83109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 831171f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 831271f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 83139566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 83147773e69fSMatthew G. Knepley } 83157773e69fSMatthew G. Knepley } 831671f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 831771f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 83189566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 83199566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 83204acb8e1eSToby Isaac } 832171f0bbf9SMatthew G. Knepley if (NclC) { 83229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 83237773e69fSMatthew G. Knepley } else { 83249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 83257773e69fSMatthew G. Knepley } 832671f0bbf9SMatthew G. Knepley 832771f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 83283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 83297773e69fSMatthew G. Knepley } 83307773e69fSMatthew G. Knepley 8331d3d1a6afSToby Isaac /*@C 8332d3d1a6afSToby Isaac DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 8333d3d1a6afSToby Isaac 8334d3d1a6afSToby Isaac Not collective 8335d3d1a6afSToby Isaac 8336d3d1a6afSToby Isaac Input Parameters: 8337d3d1a6afSToby Isaac + dm - The `DM` 8338d3d1a6afSToby Isaac . section - The `PetscSection` describing the points (a local section) 8339d3d1a6afSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 8340d3d1a6afSToby Isaac . point - The point defining the closure 8341d3d1a6afSToby Isaac - useClPerm - Use the closure point permutation if available 8342d3d1a6afSToby Isaac 8343d3d1a6afSToby Isaac Output Parameters: 8344d3d1a6afSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections 8345d3d1a6afSToby Isaac . indices - The dof indices 8346c3871b17SNoam T . outOffsets - Array, of length the number of fields plus 1, to write the field offsets into, or `NULL` 8347d3d1a6afSToby Isaac - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 8348d3d1a6afSToby Isaac 8349d3d1a6afSToby Isaac Level: advanced 8350d3d1a6afSToby Isaac 8351d3d1a6afSToby Isaac Notes: 83522c9a7b26SBarry Smith Call `DMPlexRestoreClosureIndices()` to free allocated memory 8353d3d1a6afSToby Isaac 8354d3d1a6afSToby Isaac If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 8355d3d1a6afSToby Isaac of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 8356d3d1a6afSToby Isaac of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 8357d3d1a6afSToby Isaac indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 8358d3d1a6afSToby Isaac indices (with the above semantics) are implied. 8359d3d1a6afSToby Isaac 8360d3d1a6afSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 8361d3d1a6afSToby Isaac `PetscSection`, `DMGetGlobalSection()` 8362d3d1a6afSToby Isaac @*/ 8363ce78bad3SBarry Smith PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PeOp PetscInt outOffsets[], PeOp PetscScalar *values[]) 8364d3d1a6afSToby Isaac { 8365c789d87fSToby Isaac PetscInt numRows = -1, numCols = -1; 8366d3d1a6afSToby Isaac 8367d3d1a6afSToby Isaac PetscFunctionBeginHot; 8368c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE)); 8369c789d87fSToby Isaac PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols); 8370c789d87fSToby Isaac *numIndices = numRows; 83717773e69fSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 83727773e69fSMatthew G. Knepley } 83737773e69fSMatthew G. Knepley 83747cd05799SMatthew G. Knepley /*@C 837571f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 83767cd05799SMatthew G. Knepley 83777cd05799SMatthew G. Knepley Not collective 83787cd05799SMatthew G. Knepley 83797cd05799SMatthew G. Knepley Input Parameters: 8380a1cb98faSBarry Smith + dm - The `DM` 8381a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8382a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 838371f0bbf9SMatthew G. Knepley . point - The point defining the closure 838471f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 838571f0bbf9SMatthew G. Knepley 838671f0bbf9SMatthew G. Knepley Output Parameters: 838771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 838871f0bbf9SMatthew G. Knepley . indices - The dof indices 838920f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 839020f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 839171f0bbf9SMatthew G. Knepley 8392a1cb98faSBarry Smith Level: advanced 839371f0bbf9SMatthew G. Knepley 8394a1cb98faSBarry Smith Notes: 8395a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8396a1cb98faSBarry Smith 8397a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 839871f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 839971f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 840071f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 840171f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 84027cd05799SMatthew G. Knepley 84031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 84047cd05799SMatthew G. Knepley @*/ 8405ce78bad3SBarry Smith PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PeOp PetscInt outOffsets[], PeOp PetscScalar *values[]) 8406d71ae5a4SJacob Faibussowitsch { 84077773e69fSMatthew G. Knepley PetscFunctionBegin; 84087773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84094f572ea9SToby Isaac PetscAssertPointer(indices, 7); 84109566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 84113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84127773e69fSMatthew G. Knepley } 84137773e69fSMatthew G. Knepley 8414e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8415d71ae5a4SJacob Faibussowitsch { 8416552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8417552f7358SJed Brown PetscInt *indices; 841871f0bbf9SMatthew G. Knepley PetscInt numIndices; 841971f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8420552f7358SJed Brown PetscErrorCode ierr; 8421552f7358SJed Brown 8422552f7358SJed Brown PetscFunctionBegin; 8423552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84249566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 84253dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 84269566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 84273dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8428e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8429552f7358SJed Brown 8430e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84310d644c17SKarl Rupp 84329566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8433d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 84344a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8435552f7358SJed Brown if (ierr) { 8436552f7358SJed Brown PetscMPIInt rank; 8437552f7358SJed Brown 84389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 84399566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 84409566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 84419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84429566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8443c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8444552f7358SJed Brown } 84454a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 84464a1e0b3eSMatthew G. Knepley PetscInt i; 84479566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 844863a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 84499566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 84504a1e0b3eSMatthew G. Knepley } 845171f0bbf9SMatthew G. Knepley 84529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 84539566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 84543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84554acb8e1eSToby Isaac } 845671f0bbf9SMatthew G. Knepley 84574a1e0b3eSMatthew G. Knepley /*@C 8458e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8459e8e188d2SZach Atkins 8460e8e188d2SZach Atkins Not collective 8461e8e188d2SZach Atkins 8462e8e188d2SZach Atkins Input Parameters: 8463e8e188d2SZach Atkins + dm - The `DM` 8464e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8465e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8466e8e188d2SZach Atkins . A - The matrix 8467e8e188d2SZach Atkins . point - The point in the `DM` 8468e8e188d2SZach Atkins . values - The array of values 8469e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8470e8e188d2SZach Atkins 8471e8e188d2SZach Atkins Level: intermediate 8472e8e188d2SZach Atkins 8473e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8474e8e188d2SZach Atkins @*/ 8475e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8476e8e188d2SZach Atkins { 8477e8e188d2SZach Atkins PetscFunctionBegin; 8478e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8479e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8480e8e188d2SZach Atkins } 8481e8e188d2SZach Atkins 8482e8e188d2SZach Atkins /*@C 848360225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 84844a1e0b3eSMatthew G. Knepley 84854a1e0b3eSMatthew G. Knepley Not collective 84864a1e0b3eSMatthew G. Knepley 84874a1e0b3eSMatthew G. Knepley Input Parameters: 8488a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 848920f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8490e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 849120f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8492a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 849320f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8494e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 849520f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 84964a1e0b3eSMatthew G. Knepley . A - The matrix 8497a1cb98faSBarry Smith . point - The point in the `DM` 84984a1e0b3eSMatthew G. Knepley . values - The array of values 8499a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 85004a1e0b3eSMatthew G. Knepley 85014a1e0b3eSMatthew G. Knepley Level: intermediate 85024a1e0b3eSMatthew G. Knepley 85031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 85044a1e0b3eSMatthew G. Knepley @*/ 8505e8e188d2SZach 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) 8506d71ae5a4SJacob Faibussowitsch { 850771f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 850871f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 8509c789d87fSToby Isaac PetscInt numIndicesRow = -1, numIndicesCol = -1; 85107caea556SToby Isaac const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2; 8511c789d87fSToby Isaac 851271f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 851371f0bbf9SMatthew G. Knepley 851471f0bbf9SMatthew G. Knepley PetscFunctionBegin; 851571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 85169566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 851771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 85189566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 851971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8520e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 85219566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8522e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 85239566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8524e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8525e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 852671f0bbf9SMatthew G. Knepley 8527c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow)); 8528c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol)); 85297caea556SToby Isaac valuesV1 = valuesV0; 8530c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE)); 85317caea556SToby Isaac valuesV2 = valuesV1; 8532c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE)); 853371f0bbf9SMatthew G. Knepley 8534c789d87fSToby Isaac if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2)); 8535d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8536c789d87fSToby Isaac ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode); 853771f0bbf9SMatthew G. Knepley if (ierr) { 853871f0bbf9SMatthew G. Knepley PetscMPIInt rank; 853971f0bbf9SMatthew G. Knepley 85409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 85419566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 85429566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 85437caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2)); 85447caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 85457caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 85467caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 8547d3d1a6afSToby Isaac } 854871f0bbf9SMatthew G. Knepley 85497caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2)); 85507caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 85517caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 85527caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 85533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8554552f7358SJed Brown } 8555552f7358SJed Brown 8556d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8557d71ae5a4SJacob Faibussowitsch { 8558de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8559de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8560de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8561de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 856217c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8563de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8564412e9a14SMatthew G. Knepley DMPolytopeType ct; 85654ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8566de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8567de41b84cSMatthew G. Knepley 8568de41b84cSMatthew G. Knepley PetscFunctionBegin; 8569de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8570de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 85719566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8572de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 85739566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8574de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 85759566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8576de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 85779566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8578de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8579de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 85809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 858163a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 85829566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 85839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8584de41b84cSMatthew G. Knepley /* Column indices */ 85859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85864ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8587de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8588de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 85899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8590de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8591de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8592de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8593de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8594de41b84cSMatthew G. Knepley ++q; 8595de41b84cSMatthew G. Knepley } 8596de41b84cSMatthew G. Knepley } 8597de41b84cSMatthew G. Knepley numCPoints = q; 8598de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8599de41b84cSMatthew G. Knepley PetscInt fdof; 8600de41b84cSMatthew G. Knepley 86019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 86024ca5e9f5SMatthew G. Knepley if (!dof) continue; 8603de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 86049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8605de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8606de41b84cSMatthew G. Knepley } 8607de41b84cSMatthew G. Knepley numCIndices += dof; 8608de41b84cSMatthew G. Knepley } 8609de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8610de41b84cSMatthew G. Knepley /* Row indices */ 86119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8612412e9a14SMatthew G. Knepley { 8613012bc364SMatthew G. Knepley DMPlexTransform tr; 8614012bc364SMatthew G. Knepley DMPolytopeType *rct; 8615012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8616012bc364SMatthew G. Knepley 86179566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 86189566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 86199566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8620012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 86219566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8622412e9a14SMatthew G. Knepley } 86239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8624de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8625de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 86269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8627de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 86289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8629de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8630de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 86319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 86324ca5e9f5SMatthew G. Knepley if (!dof) continue; 86339371c9d4SSatish Balay for (s = 0; s < q; ++s) 86349371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 86354ca5e9f5SMatthew G. Knepley if (s < q) continue; 8636de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8637de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8638de41b84cSMatthew G. Knepley ++q; 8639de41b84cSMatthew G. Knepley } 8640de41b84cSMatthew G. Knepley } 86419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8642de41b84cSMatthew G. Knepley } 8643de41b84cSMatthew G. Knepley numFPoints = q; 8644de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8645de41b84cSMatthew G. Knepley PetscInt fdof; 8646de41b84cSMatthew G. Knepley 86479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 86484ca5e9f5SMatthew G. Knepley if (!dof) continue; 8649de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 86509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8651de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8652de41b84cSMatthew G. Knepley } 8653de41b84cSMatthew G. Knepley numFIndices += dof; 8654de41b84cSMatthew G. Knepley } 8655de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8656de41b84cSMatthew G. Knepley 86571dca8a05SBarry 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); 86581dca8a05SBarry 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); 86599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 86609566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8661de41b84cSMatthew G. Knepley if (numFields) { 86624acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 86634acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 86644acb8e1eSToby Isaac 86654acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8668de41b84cSMatthew G. Knepley } 86694acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 86709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86719566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 86724acb8e1eSToby Isaac } 86734acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 86749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86759566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 86764acb8e1eSToby Isaac } 86774acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86789566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86799566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8680de41b84cSMatthew G. Knepley } 8681de41b84cSMatthew G. Knepley } else { 86824acb8e1eSToby Isaac const PetscInt **permsF = NULL; 86834acb8e1eSToby Isaac const PetscInt **permsC = NULL; 86844acb8e1eSToby Isaac 86859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 86869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 86874acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 86884acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 86894acb8e1eSToby Isaac 86909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86919566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8692de41b84cSMatthew G. Knepley } 86934acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 86944acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 86954acb8e1eSToby Isaac 86969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86979566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8698de41b84cSMatthew G. Knepley } 86999566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 87009566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8701de41b84cSMatthew G. Knepley } 87029566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 87034acb8e1eSToby Isaac /* TODO: flips */ 8704d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8705de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8706de41b84cSMatthew G. Knepley if (ierr) { 8707de41b84cSMatthew G. Knepley PetscMPIInt rank; 8708de41b84cSMatthew G. Knepley 87099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 87109566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 87119566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 87129566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 87139566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8714de41b84cSMatthew G. Knepley } 87159566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 87169566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 87179566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 87189566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 87193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8720de41b84cSMatthew G. Knepley } 8721de41b84cSMatthew G. Knepley 8722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8723d71ae5a4SJacob Faibussowitsch { 87247c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 87257c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8726230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 872717c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8728412e9a14SMatthew G. Knepley DMPolytopeType ct; 87297c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 87307c927364SMatthew G. Knepley 87317c927364SMatthew G. Knepley PetscFunctionBegin; 87327c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 87337c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 87349566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 87357c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 87369566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 87377c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 87389566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 87397c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 87409566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 87417c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 87429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 874363a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 87447c927364SMatthew G. Knepley /* Column indices */ 87459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 87467c927364SMatthew G. Knepley maxFPoints = numCPoints; 87477c927364SMatthew G. Knepley /* Compress out points not in the section */ 87487c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 87499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 87507c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 87517c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 87527c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 87537c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 87547c927364SMatthew G. Knepley ++q; 87557c927364SMatthew G. Knepley } 87567c927364SMatthew G. Knepley } 87577c927364SMatthew G. Knepley numCPoints = q; 87587c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 87597c927364SMatthew G. Knepley PetscInt fdof; 87607c927364SMatthew G. Knepley 87619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 87627c927364SMatthew G. Knepley if (!dof) continue; 87637c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 87649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 87657c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 87667c927364SMatthew G. Knepley } 87677c927364SMatthew G. Knepley numCIndices += dof; 87687c927364SMatthew G. Knepley } 87697c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 87707c927364SMatthew G. Knepley /* Row indices */ 87719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8772412e9a14SMatthew G. Knepley { 8773012bc364SMatthew G. Knepley DMPlexTransform tr; 8774012bc364SMatthew G. Knepley DMPolytopeType *rct; 8775012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8776012bc364SMatthew G. Knepley 87779566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 87789566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 87799566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8780012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 87819566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8782412e9a14SMatthew G. Knepley } 87839566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 87847c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 87857c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 87869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 87877c927364SMatthew G. Knepley /* Compress out points not in the section */ 87889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 87897c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 87907c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 87919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 87927c927364SMatthew G. Knepley if (!dof) continue; 87939371c9d4SSatish Balay for (s = 0; s < q; ++s) 87949371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 87957c927364SMatthew G. Knepley if (s < q) continue; 87967c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 87977c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 87987c927364SMatthew G. Knepley ++q; 87997c927364SMatthew G. Knepley } 88007c927364SMatthew G. Knepley } 88019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 88027c927364SMatthew G. Knepley } 88037c927364SMatthew G. Knepley numFPoints = q; 88047c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 88057c927364SMatthew G. Knepley PetscInt fdof; 88067c927364SMatthew G. Knepley 88079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 88087c927364SMatthew G. Knepley if (!dof) continue; 88097c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 88109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 88117c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 88127c927364SMatthew G. Knepley } 88137c927364SMatthew G. Knepley numFIndices += dof; 88147c927364SMatthew G. Knepley } 88157c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 88167c927364SMatthew G. Knepley 88171dca8a05SBarry 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); 88181dca8a05SBarry 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); 88197c927364SMatthew G. Knepley if (numFields) { 88204acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 88214acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 88224acb8e1eSToby Isaac 88234acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 88249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 88259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 88267c927364SMatthew G. Knepley } 88274acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 88289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 88299566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 88304acb8e1eSToby Isaac } 88314acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 88329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 88339566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 88344acb8e1eSToby Isaac } 88354acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 88369566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 88379566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 88387c927364SMatthew G. Knepley } 88397c927364SMatthew G. Knepley } else { 88404acb8e1eSToby Isaac const PetscInt **permsF = NULL; 88414acb8e1eSToby Isaac const PetscInt **permsC = NULL; 88424acb8e1eSToby Isaac 88439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 88449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 88454acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 88464acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 88474acb8e1eSToby Isaac 88489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 88499566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 88507c927364SMatthew G. Knepley } 88514acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 88524acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 88534acb8e1eSToby Isaac 88549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 88559566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 88567c927364SMatthew G. Knepley } 88579566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 88589566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 88597c927364SMatthew G. Knepley } 88609566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 88619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 88623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 88637c927364SMatthew G. Knepley } 88647c927364SMatthew G. Knepley 8865cc4c1da9SBarry Smith /*@ 88667cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 88677cd05799SMatthew G. Knepley 88687cd05799SMatthew G. Knepley Input Parameter: 8869a1cb98faSBarry Smith . dm - The `DMPLEX` object 88707cd05799SMatthew G. Knepley 88717cd05799SMatthew G. Knepley Output Parameter: 88727cd05799SMatthew G. Knepley . cellHeight - The height of a cell 88737cd05799SMatthew G. Knepley 88747cd05799SMatthew G. Knepley Level: developer 88757cd05799SMatthew G. Knepley 88761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 88777cd05799SMatthew G. Knepley @*/ 8878d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8879d71ae5a4SJacob Faibussowitsch { 8880552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8881552f7358SJed Brown 8882552f7358SJed Brown PetscFunctionBegin; 8883552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88844f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8885552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 88863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8887552f7358SJed Brown } 8888552f7358SJed Brown 8889cc4c1da9SBarry Smith /*@ 88907cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 88917cd05799SMatthew G. Knepley 88927cd05799SMatthew G. Knepley Input Parameters: 8893a1cb98faSBarry Smith + dm - The `DMPLEX` object 88947cd05799SMatthew G. Knepley - cellHeight - The height of a cell 88957cd05799SMatthew G. Knepley 88967cd05799SMatthew G. Knepley Level: developer 88977cd05799SMatthew G. Knepley 88981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 88997cd05799SMatthew G. Knepley @*/ 8900d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8901d71ae5a4SJacob Faibussowitsch { 8902552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8903552f7358SJed Brown 8904552f7358SJed Brown PetscFunctionBegin; 8905552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8906552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 89073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8908552f7358SJed Brown } 8909552f7358SJed Brown 8910e6139122SMatthew G. Knepley /*@ 89112827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8912e6139122SMatthew G. Knepley 89132827ebadSStefano Zampini Input Parameters: 89142827ebadSStefano Zampini + dm - The `DMPLEX` object 89152827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8916e6139122SMatthew G. Knepley 8917e6139122SMatthew G. Knepley Output Parameters: 89182827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 89192827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8920e6139122SMatthew G. Knepley 89212a9f31c0SMatthew G. Knepley Level: advanced 8922e6139122SMatthew G. Knepley 89232827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8924e6139122SMatthew G. Knepley @*/ 8925ce78bad3SBarry Smith PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PeOp PetscInt *start, PeOp PetscInt *end) 8926d71ae5a4SJacob Faibussowitsch { 89272827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 89282827ebadSStefano Zampini DMLabel label; 89292827ebadSStefano Zampini PetscInt pStart, pEnd; 8930e6139122SMatthew G. Knepley 8931e6139122SMatthew G. Knepley PetscFunctionBegin; 8932e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89332827ebadSStefano Zampini if (start) { 89344f572ea9SToby Isaac PetscAssertPointer(start, 3); 89352827ebadSStefano Zampini *start = 0; 89362827ebadSStefano Zampini } 89372827ebadSStefano Zampini if (end) { 89384f572ea9SToby Isaac PetscAssertPointer(end, 4); 89392827ebadSStefano Zampini *end = 0; 89402827ebadSStefano Zampini } 89412827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 89422827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 89432827ebadSStefano Zampini if (mesh->tr) { 89442827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 89452827ebadSStefano Zampini } else { 89462827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 89472827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 89482827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 89492827ebadSStefano Zampini } 89503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8951e6139122SMatthew G. Knepley } 8952e6139122SMatthew G. Knepley 895321c42226SMatthew G. Knepley /*@ 895421c42226SMatthew G. Knepley DMPlexGetDepthStratumGlobalSize - Get the global size for a given depth stratum 895521c42226SMatthew G. Knepley 895621c42226SMatthew G. Knepley Input Parameters: 895721c42226SMatthew G. Knepley + dm - The `DMPLEX` object 895821c42226SMatthew G. Knepley - depth - The depth for the given point stratum 895921c42226SMatthew G. Knepley 896021c42226SMatthew G. Knepley Output Parameter: 896121c42226SMatthew G. Knepley . gsize - The global number of points in the stratum 896221c42226SMatthew G. Knepley 896321c42226SMatthew G. Knepley Level: advanced 896421c42226SMatthew G. Knepley 896521c42226SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 896621c42226SMatthew G. Knepley @*/ 896721c42226SMatthew G. Knepley PetscErrorCode DMPlexGetDepthStratumGlobalSize(DM dm, PetscInt depth, PetscInt *gsize) 896821c42226SMatthew G. Knepley { 896921c42226SMatthew G. Knepley PetscSF sf; 897021c42226SMatthew G. Knepley const PetscInt *leaves; 897121c42226SMatthew G. Knepley PetscInt Nl, loc, start, end, lsize = 0; 897221c42226SMatthew G. Knepley 897321c42226SMatthew G. Knepley PetscFunctionBegin; 897421c42226SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 897521c42226SMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 897621c42226SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, depth, &start, &end)); 897721c42226SMatthew G. Knepley for (PetscInt p = start; p < end; ++p) { 897821c42226SMatthew G. Knepley PetscCall(PetscFindInt(p, Nl, leaves, &loc)); 897921c42226SMatthew G. Knepley if (loc < 0) ++lsize; 898021c42226SMatthew G. Knepley } 8981458b0db5SMartin Diehl PetscCallMPI(MPIU_Allreduce(&lsize, gsize, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 898221c42226SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 898321c42226SMatthew G. Knepley } 898421c42226SMatthew G. Knepley 8985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8986d71ae5a4SJacob Faibussowitsch { 8987552f7358SJed Brown PetscSection section, globalSection; 8988552f7358SJed Brown PetscInt *numbers, p; 8989552f7358SJed Brown 8990552f7358SJed Brown PetscFunctionBegin; 8991d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 89929566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 89939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 899448a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 89959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8996eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 89979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8998552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 89999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 9000ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 9001ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 9002552f7358SJed Brown } 90039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 9004ef48cebcSMatthew G. Knepley if (globalSize) { 9005ef48cebcSMatthew G. Knepley PetscLayout layout; 90069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 90079566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 90089566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 9009ef48cebcSMatthew G. Knepley } 90109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 90119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 90123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9013552f7358SJed Brown } 9014552f7358SJed Brown 9015e2b8d0fcSMatthew G. Knepley /*@ 9016e2b8d0fcSMatthew G. Knepley DMPlexCreateCellNumbering - Get a global cell numbering for all cells on this process 9017e2b8d0fcSMatthew G. Knepley 9018bc9da2b0SJose E. Roman Input Parameters: 9019e2b8d0fcSMatthew G. Knepley + dm - The `DMPLEX` object 9020e2b8d0fcSMatthew G. Knepley - includeAll - Whether to include all cells, or just the simplex and box cells 9021e2b8d0fcSMatthew G. Knepley 9022e2b8d0fcSMatthew G. Knepley Output Parameter: 9023e2b8d0fcSMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 9024e2b8d0fcSMatthew G. Knepley 9025e2b8d0fcSMatthew G. Knepley Level: developer 9026e2b8d0fcSMatthew G. Knepley 9027e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()` 9028e2b8d0fcSMatthew G. Knepley @*/ 9029e2b8d0fcSMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering(DM dm, PetscBool includeAll, IS *globalCellNumbers) 9030d71ae5a4SJacob Faibussowitsch { 9031412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 9032552f7358SJed Brown 9033552f7358SJed Brown PetscFunctionBegin; 90349566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 9035e2b8d0fcSMatthew G. Knepley if (includeAll) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90369566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 90379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 90383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9039552f7358SJed Brown } 904081ed3555SMatthew G. Knepley 90418dab3259SMatthew G. Knepley /*@ 90427cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 90437cd05799SMatthew G. Knepley 90447cd05799SMatthew G. Knepley Input Parameter: 9045a1cb98faSBarry Smith . dm - The `DMPLEX` object 90467cd05799SMatthew G. Knepley 90477cd05799SMatthew G. Knepley Output Parameter: 90487cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 90497cd05799SMatthew G. Knepley 90507cd05799SMatthew G. Knepley Level: developer 90517cd05799SMatthew G. Knepley 9052e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateCellNumbering()`, `DMPlexGetVertexNumbering()` 90537cd05799SMatthew G. Knepley @*/ 9054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9055d71ae5a4SJacob Faibussowitsch { 905681ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 905781ed3555SMatthew G. Knepley 905881ed3555SMatthew G. Knepley PetscFunctionBegin; 905981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9060e2b8d0fcSMatthew G. Knepley if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 9061552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 90623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9063552f7358SJed Brown } 9064552f7358SJed Brown 9065d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 9066d71ae5a4SJacob Faibussowitsch { 9067412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 906881ed3555SMatthew G. Knepley 906981ed3555SMatthew G. Knepley PetscFunctionBegin; 907081ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 90729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 90733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 907481ed3555SMatthew G. Knepley } 907581ed3555SMatthew G. Knepley 90768dab3259SMatthew G. Knepley /*@ 90776aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 90787cd05799SMatthew G. Knepley 90797cd05799SMatthew G. Knepley Input Parameter: 9080a1cb98faSBarry Smith . dm - The `DMPLEX` object 90817cd05799SMatthew G. Knepley 90827cd05799SMatthew G. Knepley Output Parameter: 90837cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 90847cd05799SMatthew G. Knepley 90857cd05799SMatthew G. Knepley Level: developer 90867cd05799SMatthew G. Knepley 90871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 90887cd05799SMatthew G. Knepley @*/ 9089d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9090d71ae5a4SJacob Faibussowitsch { 9091552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9092552f7358SJed Brown 9093552f7358SJed Brown PetscFunctionBegin; 9094552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90959566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 9096552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 90973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9098552f7358SJed Brown } 9099552f7358SJed Brown 91008dab3259SMatthew G. Knepley /*@ 9101966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 9102966484cfSJed Brown 910320f4b53cSBarry Smith Collective 91047cd05799SMatthew G. Knepley 91057cd05799SMatthew G. Knepley Input Parameter: 9106a1cb98faSBarry Smith . dm - The `DMPLEX` object 91077cd05799SMatthew G. Knepley 91087cd05799SMatthew G. Knepley Output Parameter: 91097cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 91107cd05799SMatthew G. Knepley 9111a1cb98faSBarry Smith Level: developer 9112966484cfSJed Brown 9113a1cb98faSBarry Smith Notes: 9114a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 9115966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 9116966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 9117966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 9118966484cfSJed Brown 9119966484cfSJed Brown The partitioned mesh is 9120966484cfSJed Brown ``` 9121966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 9122966484cfSJed Brown ``` 9123966484cfSJed Brown and its global numbering is 9124966484cfSJed Brown ``` 9125966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 9126966484cfSJed Brown ``` 9127966484cfSJed Brown Then the global numbering is provided as 9128966484cfSJed Brown ``` 9129966484cfSJed Brown [0] Number of indices in set 5 9130966484cfSJed Brown [0] 0 0 9131966484cfSJed Brown [0] 1 1 9132966484cfSJed Brown [0] 2 3 9133966484cfSJed Brown [0] 3 4 9134966484cfSJed Brown [0] 4 -6 9135966484cfSJed Brown [1] Number of indices in set 3 9136966484cfSJed Brown [1] 0 2 9137966484cfSJed Brown [1] 1 5 9138966484cfSJed Brown [1] 2 6 9139966484cfSJed Brown ``` 9140966484cfSJed Brown 91411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 91427cd05799SMatthew G. Knepley @*/ 9143d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 9144d71ae5a4SJacob Faibussowitsch { 9145ef48cebcSMatthew G. Knepley IS nums[4]; 9146862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 9147ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 91480c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 9149ef48cebcSMatthew G. Knepley 9150ef48cebcSMatthew G. Knepley PetscFunctionBegin; 9151ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 91530c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 91549566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 91550c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 9156862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 9157862913ffSStefano Zampini PetscInt end; 9158862913ffSStefano Zampini 9159862913ffSStefano Zampini depths[d] = depth - d; 91609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 91610c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 9162862913ffSStefano Zampini } 91630c15888dSMatthew G. Knepley if (empty) 91640c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 91650c15888dSMatthew G. Knepley depths[d] = -1; 91660c15888dSMatthew G. Knepley starts[d] = -1; 91670c15888dSMatthew G. Knepley } 91680c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 9169e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 9170ad540459SPierre 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]); 91710c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 9172ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 9173ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 9174ef48cebcSMatthew G. Knepley 91759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 91769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 9177ef48cebcSMatthew G. Knepley shift += gsize; 9178ef48cebcSMatthew G. Knepley } 9179d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 91809566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 91813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9182ef48cebcSMatthew G. Knepley } 9183ef48cebcSMatthew G. Knepley 918408a22f4bSMatthew G. Knepley /*@ 9185484edb7dSMatthew G. Knepley DMPlexCreateEdgeNumbering - Create a global numbering for edges. 9186484edb7dSMatthew G. Knepley 9187484edb7dSMatthew G. Knepley Collective 9188484edb7dSMatthew G. Knepley 9189484edb7dSMatthew G. Knepley Input Parameter: 9190484edb7dSMatthew G. Knepley . dm - The `DMPLEX` object 9191484edb7dSMatthew G. Knepley 9192484edb7dSMatthew G. Knepley Output Parameter: 9193484edb7dSMatthew G. Knepley . globalEdgeNumbers - Global numbers for all edges on this process 9194484edb7dSMatthew G. Knepley 9195484edb7dSMatthew G. Knepley Level: developer 9196484edb7dSMatthew G. Knepley 9197484edb7dSMatthew G. Knepley Notes: 9198484edb7dSMatthew 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). 9199484edb7dSMatthew G. Knepley 9200484edb7dSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()`, `DMPlexCreatePointNumbering()` 9201484edb7dSMatthew G. Knepley @*/ 9202484edb7dSMatthew G. Knepley PetscErrorCode DMPlexCreateEdgeNumbering(DM dm, IS *globalEdgeNumbers) 9203484edb7dSMatthew G. Knepley { 9204484edb7dSMatthew G. Knepley PetscSF sf; 9205484edb7dSMatthew G. Knepley PetscInt eStart, eEnd; 9206484edb7dSMatthew G. Knepley 9207484edb7dSMatthew G. Knepley PetscFunctionBegin; 9208484edb7dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9209484edb7dSMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 9210484edb7dSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9211484edb7dSMatthew G. Knepley PetscCall(DMPlexCreateNumbering_Plex(dm, eStart, eEnd, 0, NULL, sf, globalEdgeNumbers)); 9212484edb7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 9213484edb7dSMatthew G. Knepley } 9214484edb7dSMatthew G. Knepley 9215484edb7dSMatthew G. Knepley /*@ 921608a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 921708a22f4bSMatthew G. Knepley 921808a22f4bSMatthew G. Knepley Input Parameter: 9219a1cb98faSBarry Smith . dm - The `DMPLEX` object 922008a22f4bSMatthew G. Knepley 922108a22f4bSMatthew G. Knepley Output Parameter: 922208a22f4bSMatthew G. Knepley . ranks - The rank field 922308a22f4bSMatthew G. Knepley 9224a1cb98faSBarry Smith Options Database Key: 922520f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 922608a22f4bSMatthew G. Knepley 922708a22f4bSMatthew G. Knepley Level: intermediate 922808a22f4bSMatthew G. Knepley 92291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 923008a22f4bSMatthew G. Knepley @*/ 9231d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 9232d71ae5a4SJacob Faibussowitsch { 923308a22f4bSMatthew G. Knepley DM rdm; 923408a22f4bSMatthew G. Knepley PetscFE fe; 923508a22f4bSMatthew G. Knepley PetscScalar *r; 923608a22f4bSMatthew G. Knepley PetscMPIInt rank; 9237a55f9a55SMatthew G. Knepley DMPolytopeType ct; 923808a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 9239a55f9a55SMatthew G. Knepley PetscBool simplex; 924008a22f4bSMatthew G. Knepley 924108a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 9242f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92434f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 92449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 92459566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 92469566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 92479566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 92489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 9249a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 92509566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 92519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 92529566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 92539566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 92549566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 92559566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 92569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 92579566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 925808a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 925908a22f4bSMatthew G. Knepley PetscScalar *lr; 926008a22f4bSMatthew G. Knepley 92619566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 926271f09efeSPierre Jolivet if (lr) *lr = rank; 926308a22f4bSMatthew G. Knepley } 92649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 92659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 92663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 926708a22f4bSMatthew G. Knepley } 926808a22f4bSMatthew G. Knepley 9269ca8062c8SMatthew G. Knepley /*@ 9270acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 927118e14f0cSMatthew G. Knepley 927218e14f0cSMatthew G. Knepley Input Parameters: 927320f4b53cSBarry Smith + dm - The `DMPLEX` 927420f4b53cSBarry Smith - label - The `DMLabel` 927518e14f0cSMatthew G. Knepley 927618e14f0cSMatthew G. Knepley Output Parameter: 927718e14f0cSMatthew G. Knepley . val - The label value field 927818e14f0cSMatthew G. Knepley 927920f4b53cSBarry Smith Options Database Key: 928020f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 928118e14f0cSMatthew G. Knepley 928218e14f0cSMatthew G. Knepley Level: intermediate 928318e14f0cSMatthew G. Knepley 92841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 928518e14f0cSMatthew G. Knepley @*/ 9286d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 9287d71ae5a4SJacob Faibussowitsch { 92881033741fSStefano Zampini DM rdm, plex; 9289acf3173eSStefano Zampini Vec lval; 9290acf3173eSStefano Zampini PetscSection section; 929118e14f0cSMatthew G. Knepley PetscFE fe; 929218e14f0cSMatthew G. Knepley PetscScalar *v; 9293acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 9294acf3173eSStefano Zampini DMPolytopeType ct; 9295acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 9296acf3173eSStefano Zampini const char *lname, *prefix; 929718e14f0cSMatthew G. Knepley 929818e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 929918e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93004f572ea9SToby Isaac PetscAssertPointer(label, 2); 93014f572ea9SToby Isaac PetscAssertPointer(val, 3); 93029566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 9303acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 9304acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 9305acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 9306acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 93079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 9308acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 9309acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 9310acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 9311acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 9312acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 93139566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 93149566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 93159566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 93169566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 9317acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 9318acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 9319acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 9320acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 9321acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 9322acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 9323acf3173eSStefano Zampini PetscInt cval, dof, off; 932418e14f0cSMatthew G. Knepley 9325acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 9326acf3173eSStefano Zampini if (!dof) continue; 9327acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 9328acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 9329acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 933018e14f0cSMatthew G. Knepley } 9331acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 9332acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 9333acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 93349566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 93353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 933618e14f0cSMatthew G. Knepley } 933718e14f0cSMatthew G. Knepley 933818e14f0cSMatthew G. Knepley /*@ 9339ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 9340ca8062c8SMatthew G. Knepley 934169916449SMatthew G. Knepley Input Parameter: 9342a1cb98faSBarry Smith . dm - The `DMPLEX` object 9343a1cb98faSBarry Smith 9344a1cb98faSBarry Smith Level: developer 9345ca8062c8SMatthew G. Knepley 934695eb5ee5SVaclav Hapla Notes: 934795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 934895eb5ee5SVaclav Hapla 934920f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9350ca8062c8SMatthew G. Knepley 93511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9352ca8062c8SMatthew G. Knepley @*/ 9353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 9354d71ae5a4SJacob Faibussowitsch { 9355ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 9356ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 9357ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 935857beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 935957beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9360ca8062c8SMatthew G. Knepley 9361ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9362ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93639566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 93649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 93659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9366ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 93679566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9368ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 93699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 93709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9371ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 937242e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 937342e66dfaSMatthew G. Knepley PetscInt d; 937442e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 93759371c9d4SSatish Balay if (cone[c] == cone[d]) { 93769371c9d4SSatish Balay dup = PETSC_TRUE; 93779371c9d4SSatish Balay break; 93789371c9d4SSatish Balay } 937942e66dfaSMatthew G. Knepley } 93809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 93819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9382ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9383ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9384ca8062c8SMatthew G. Knepley } 938542e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 938663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 938748a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 93889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 938963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 939048a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 93919566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 939263a3b9bcSJacob 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]); 9393f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9394ca8062c8SMatthew G. Knepley } 939542e66dfaSMatthew G. Knepley } 93969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 93979371c9d4SSatish Balay if (p != pp) { 93989371c9d4SSatish Balay storagecheck = PETSC_FALSE; 93999371c9d4SSatish Balay continue; 94009371c9d4SSatish Balay } 94019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 94029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9403ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 94049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 94059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9406ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 94079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 94089371c9d4SSatish Balay if (cone[c] != pp) { 94099371c9d4SSatish Balay c = 0; 94109371c9d4SSatish Balay break; 94119371c9d4SSatish Balay } 9412ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9413ca8062c8SMatthew G. Knepley } 9414ca8062c8SMatthew G. Knepley if (c >= coneSize) { 941563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 941648a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 94179566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 941863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 941948a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 94209566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 942163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9422ca8062c8SMatthew G. Knepley } 9423ca8062c8SMatthew G. Knepley } 9424ca8062c8SMatthew G. Knepley } 942557beb4faSStefano Zampini if (storagecheck) { 94269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 94279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 942863a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 942957beb4faSStefano Zampini } 94303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9431ca8062c8SMatthew G. Knepley } 9432ca8062c8SMatthew G. Knepley 9433412e9a14SMatthew G. Knepley /* 9434412e9a14SMatthew 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. 9435412e9a14SMatthew G. Knepley */ 9436d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9437d71ae5a4SJacob Faibussowitsch { 9438412e9a14SMatthew G. Knepley DMPolytopeType cct; 9439412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9440412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9441412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9442412e9a14SMatthew G. Knepley 9443412e9a14SMatthew G. Knepley PetscFunctionBegin; 9444412e9a14SMatthew G. Knepley *unsplit = 0; 9445412e9a14SMatthew G. Knepley switch (ct) { 9446d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9447d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9448d71ae5a4SJacob Faibussowitsch break; 9449412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 94509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 94519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9452412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 94539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9454412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9455412e9a14SMatthew G. Knepley } 9456412e9a14SMatthew G. Knepley break; 9457412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9458412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 94599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 94609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9461412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 94629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 94639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9464412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 94659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9466412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9467412e9a14SMatthew G. Knepley PetscInt p; 94689371c9d4SSatish Balay for (p = 0; p < npt; ++p) 94699371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9470412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9471412e9a14SMatthew G. Knepley } 9472412e9a14SMatthew G. Knepley } 9473412e9a14SMatthew G. Knepley } 9474412e9a14SMatthew G. Knepley break; 9475d71ae5a4SJacob Faibussowitsch default: 9476d71ae5a4SJacob Faibussowitsch break; 9477412e9a14SMatthew G. Knepley } 9478412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 94799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9480412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9481412e9a14SMatthew G. Knepley } 94823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9483412e9a14SMatthew G. Knepley } 9484412e9a14SMatthew G. Knepley 9485ca8062c8SMatthew G. Knepley /*@ 9486ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9487ca8062c8SMatthew G. Knepley 9488ca8062c8SMatthew G. Knepley Input Parameters: 9489a1cb98faSBarry Smith + dm - The `DMPLEX` object 949058723a97SMatthew G. Knepley - cellHeight - Normally 0 9491ca8062c8SMatthew G. Knepley 9492a1cb98faSBarry Smith Level: developer 9493a1cb98faSBarry Smith 949495eb5ee5SVaclav Hapla Notes: 949595eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 949625c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9497ca8062c8SMatthew G. Knepley 949820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 949995eb5ee5SVaclav Hapla 95001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9501ca8062c8SMatthew G. Knepley @*/ 9502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9503d71ae5a4SJacob Faibussowitsch { 9504412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9505412e9a14SMatthew G. Knepley DMPolytopeType ct; 9506412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9507ca8062c8SMatthew G. Knepley 9508ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9509ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95109566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 95119566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 95129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9513412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9514412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9515412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 951658723a97SMatthew G. Knepley 95179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9518412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9519412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 95209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 952163a3b9bcSJacob 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)); 9522412e9a14SMatthew G. Knepley } 95239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 952458723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 952558723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9526412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 952758723a97SMatthew G. Knepley } 95289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9529412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9530412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9531412e9a14SMatthew G. Knepley PetscInt unsplit; 953242363296SMatthew G. Knepley 95339566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9534412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 953542363296SMatthew G. Knepley } 953663a3b9bcSJacob 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)); 953742363296SMatthew G. Knepley } 95383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9539ca8062c8SMatthew G. Knepley } 95409bf0dad6SMatthew G. Knepley 95419bf0dad6SMatthew G. Knepley /*@ 95429bf0dad6SMatthew 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 95439bf0dad6SMatthew G. Knepley 954420f4b53cSBarry Smith Collective 9545899ea2b8SJacob Faibussowitsch 95469bf0dad6SMatthew G. Knepley Input Parameters: 9547a1cb98faSBarry Smith + dm - The `DMPLEX` object 95489bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 95499bf0dad6SMatthew G. Knepley 9550a1cb98faSBarry Smith Level: developer 9551a1cb98faSBarry Smith 955245da879fSVaclav Hapla Notes: 955345da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 955445da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 955545da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 955645da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 95579bf0dad6SMatthew G. Knepley 9558a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 955995eb5ee5SVaclav Hapla 95601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 95619bf0dad6SMatthew G. Knepley @*/ 9562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9563d71ae5a4SJacob Faibussowitsch { 9564ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9565899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 95669bf0dad6SMatthew G. Knepley 95679bf0dad6SMatthew G. Knepley PetscFunctionBegin; 95689bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95698f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 95703ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 95718f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 95723ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 95733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9574899ea2b8SJacob Faibussowitsch } 9575899ea2b8SJacob Faibussowitsch 95769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 95779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 95789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9579ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 95809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 95813554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9582412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9583412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9584ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9585412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9586412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 95879bf0dad6SMatthew G. Knepley 95889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 95899566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9590412e9a14SMatthew G. Knepley if (unsplit) continue; 95919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 95929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 95939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 95949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 95959bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 95969bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 95979bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 95989bf0dad6SMatthew G. Knepley } 95999566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 960063a3b9bcSJacob 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); 96019bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9602d4961f80SStefano Zampini DMPolytopeType fct; 96039bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 96049bf0dad6SMatthew G. Knepley 96059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 96069566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 96079bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 96089bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 96099bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 96109bf0dad6SMatthew G. Knepley } 961163a3b9bcSJacob 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]); 96129bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9613b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9614b5a892a1SMatthew G. Knepley PetscInt v1; 9615b5a892a1SMatthew G. Knepley 96169566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 961763a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 96189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 961963a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 96209566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 962163a3b9bcSJacob 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]); 9622b5a892a1SMatthew G. Knepley } 96239bf0dad6SMatthew G. Knepley } 96249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9625412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 96269bf0dad6SMatthew G. Knepley } 96279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 96289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 96299bf0dad6SMatthew G. Knepley } 96303554e41dSMatthew G. Knepley } 96313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9632552f7358SJed Brown } 96333913d7c8SMatthew G. Knepley 9634bb6a34a8SMatthew G. Knepley /*@ 9635bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9636bb6a34a8SMatthew G. Knepley 9637bb6a34a8SMatthew G. Knepley Input Parameter: 9638a1cb98faSBarry Smith . dm - The `DMPLEX` object 9639a1cb98faSBarry Smith 9640a1cb98faSBarry Smith Level: developer 9641bb6a34a8SMatthew G. Knepley 964295eb5ee5SVaclav Hapla Notes: 964395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 964495eb5ee5SVaclav Hapla 964520f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9646bb6a34a8SMatthew G. Knepley 96471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9648bb6a34a8SMatthew G. Knepley @*/ 9649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9650d71ae5a4SJacob Faibussowitsch { 9651a2a9e04cSMatthew G. Knepley Vec coordinates; 9652bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9653bb6a34a8SMatthew G. Knepley PetscReal vol; 965451a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9655bb6a34a8SMatthew G. Knepley 9656bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 96579566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 96589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 96593ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 96609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9661bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 96629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9663a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 96649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 96653ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9666412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9667412e9a14SMatthew G. Knepley DMPolytopeType ct; 9668412e9a14SMatthew G. Knepley PetscInt unsplit; 9669412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9670412e9a14SMatthew G. Knepley 96719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9672412e9a14SMatthew G. Knepley switch (ct) { 9673412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9674412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9675d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9676d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9677d71ae5a4SJacob Faibussowitsch break; 9678d71ae5a4SJacob Faibussowitsch default: 9679d71ae5a4SJacob Faibussowitsch break; 9680412e9a14SMatthew G. Knepley } 9681412e9a14SMatthew G. Knepley switch (ct) { 9682412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9683412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9684412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9685d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9686d71ae5a4SJacob Faibussowitsch continue; 9687d71ae5a4SJacob Faibussowitsch default: 9688d71ae5a4SJacob Faibussowitsch break; 9689412e9a14SMatthew G. Knepley } 96909566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9691412e9a14SMatthew G. Knepley if (unsplit) continue; 96929566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 96931dca8a05SBarry 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); 969463a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 96956858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 96966858538eSMatthew G. Knepley if (depth > 1) { 96979566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 96981dca8a05SBarry 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); 969963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9700bb6a34a8SMatthew G. Knepley } 9701bb6a34a8SMatthew G. Knepley } 97023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9703bb6a34a8SMatthew G. Knepley } 9704bb6a34a8SMatthew G. Knepley 970503da9461SVaclav Hapla /*@ 970620f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 97077726db96SVaclav Hapla 970820f4b53cSBarry Smith Collective 970903da9461SVaclav Hapla 971003da9461SVaclav Hapla Input Parameters: 9711a1cb98faSBarry Smith + dm - The `DMPLEX` object 971220f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9713a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9714a1cb98faSBarry Smith 9715a1cb98faSBarry Smith Level: developer 971603da9461SVaclav Hapla 9717e83a0d2dSVaclav Hapla Notes: 9718e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 971903da9461SVaclav Hapla 9720a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 972195eb5ee5SVaclav Hapla 9722baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9723d7d32a9aSMatthew G. Knepley 97241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 972503da9461SVaclav Hapla @*/ 9726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9727d71ae5a4SJacob Faibussowitsch { 97287726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 97297726db96SVaclav Hapla const PetscInt *locals; 97307726db96SVaclav Hapla const PetscSFNode *remotes; 9731f0cfc026SVaclav Hapla PetscBool distributed; 97327726db96SVaclav Hapla MPI_Comm comm; 97337726db96SVaclav Hapla PetscMPIInt rank; 973403da9461SVaclav Hapla 973503da9461SVaclav Hapla PetscFunctionBegin; 973603da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97377726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 97387726db96SVaclav Hapla else pointSF = dm->sf; 97397726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 97407726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 97417726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 97427726db96SVaclav Hapla { 97437726db96SVaclav Hapla PetscMPIInt mpiFlag; 97447726db96SVaclav Hapla 97457726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 97467726db96SVaclav 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); 97477726db96SVaclav Hapla } 97487726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 97499566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 97507726db96SVaclav Hapla if (!distributed) { 97517726db96SVaclav 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); 97523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97538918e3e2SVaclav Hapla } 97547726db96SVaclav 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); 97557726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 975603da9461SVaclav Hapla 97577726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 97587726db96SVaclav Hapla { 97597726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 97607726db96SVaclav Hapla 97617726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 97627726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9763d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 97647726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 97657726db96SVaclav Hapla } 97667726db96SVaclav Hapla 97677726db96SVaclav Hapla /* Check there are no cells in interface */ 97687726db96SVaclav Hapla if (!overlap) { 97697726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 97707726db96SVaclav Hapla 97719566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97729566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9773f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 97747726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9775f5869d18SMatthew G. Knepley 97767726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 97777726db96SVaclav Hapla } 977803da9461SVaclav Hapla } 9779ece87651SVaclav Hapla 97807726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 97817726db96SVaclav Hapla { 97827726db96SVaclav Hapla const PetscInt *rootdegree; 97837726db96SVaclav Hapla 97847726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 97857726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9786f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 97877726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9788f5869d18SMatthew G. Knepley const PetscInt *cone; 9789f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9790f5869d18SMatthew G. Knepley 97919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 97929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9793f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9794f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 97957726db96SVaclav Hapla if (locals) { 97969566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 97977726db96SVaclav Hapla } else { 97987726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 97997726db96SVaclav Hapla } 980063a3b9bcSJacob 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]); 9801f5869d18SMatthew G. Knepley } 9802f5869d18SMatthew G. Knepley } 9803ece87651SVaclav Hapla } 98047726db96SVaclav Hapla } 98053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 980603da9461SVaclav Hapla } 980703da9461SVaclav Hapla 98087f9d8d6cSVaclav Hapla /*@ 9809217fe35eSMatthew G. Knepley DMPlexCheckOrphanVertices - Check that no vertices are disconnected from the mesh, unless the mesh only consists of disconnected vertices. 9810217fe35eSMatthew G. Knepley 9811217fe35eSMatthew G. Knepley Collective 9812217fe35eSMatthew G. Knepley 9813217fe35eSMatthew G. Knepley Input Parameter: 9814217fe35eSMatthew G. Knepley . dm - The `DMPLEX` object 9815217fe35eSMatthew G. Knepley 9816217fe35eSMatthew G. Knepley Level: developer 9817217fe35eSMatthew G. Knepley 9818217fe35eSMatthew G. Knepley Notes: 9819217fe35eSMatthew G. Knepley This is mainly intended for debugging/testing purposes. 9820217fe35eSMatthew G. Knepley 9821217fe35eSMatthew G. Knepley Other cell types which are disconnected would be caught by the symmetry and face checks. 9822217fe35eSMatthew G. Knepley 9823217fe35eSMatthew G. Knepley For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9824217fe35eSMatthew G. Knepley 9825217fe35eSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheck()`, `DMSetFromOptions()` 9826217fe35eSMatthew G. Knepley @*/ 9827217fe35eSMatthew G. Knepley PetscErrorCode DMPlexCheckOrphanVertices(DM dm) 9828217fe35eSMatthew G. Knepley { 9829217fe35eSMatthew G. Knepley PetscInt pStart, pEnd, vStart, vEnd; 9830217fe35eSMatthew G. Knepley 9831217fe35eSMatthew G. Knepley PetscFunctionBegin; 9832217fe35eSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9833217fe35eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9834217fe35eSMatthew G. Knepley if (pStart == vStart && pEnd == vEnd) PetscFunctionReturn(PETSC_SUCCESS); 9835217fe35eSMatthew G. Knepley for (PetscInt v = vStart; v < vEnd; ++v) { 9836217fe35eSMatthew G. Knepley PetscInt suppSize; 9837217fe35eSMatthew G. Knepley 9838217fe35eSMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, v, &suppSize)); 9839217fe35eSMatthew G. Knepley PetscCheck(suppSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is disconnected from the mesh", v); 9840217fe35eSMatthew G. Knepley } 9841217fe35eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 9842217fe35eSMatthew G. Knepley } 9843217fe35eSMatthew G. Knepley 9844217fe35eSMatthew G. Knepley /*@ 984520f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 98467f9d8d6cSVaclav Hapla 98477f9d8d6cSVaclav Hapla Input Parameter: 9848a1cb98faSBarry Smith . dm - The `DMPLEX` object 9849a1cb98faSBarry Smith 9850a1cb98faSBarry Smith Level: developer 98517f9d8d6cSVaclav Hapla 98527f9d8d6cSVaclav Hapla Notes: 98537f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 98547f9d8d6cSVaclav Hapla 985520f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 98567f9d8d6cSVaclav Hapla 985720f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 98587f9d8d6cSVaclav Hapla 98591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 98607f9d8d6cSVaclav Hapla @*/ 9861d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9862d71ae5a4SJacob Faibussowitsch { 98637f9d8d6cSVaclav Hapla PetscInt cellHeight; 98647f9d8d6cSVaclav Hapla 9865b5a892a1SMatthew G. Knepley PetscFunctionBegin; 98667f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 98679566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 98689566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 98699566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 98709566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9871d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 98729566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 9873217fe35eSMatthew G. Knepley PetscCall(DMPlexCheckOrphanVertices(dm)); 98743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9875b5a892a1SMatthew G. Knepley } 9876b5a892a1SMatthew G. Knepley 98779371c9d4SSatish Balay typedef struct cell_stats { 9878068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9879068a5610SStefano Zampini PetscInt count; 9880068a5610SStefano Zampini } cell_stats_t; 9881068a5610SStefano Zampini 9882d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9883d71ae5a4SJacob Faibussowitsch { 9884068a5610SStefano Zampini PetscInt i, N = *len; 9885068a5610SStefano Zampini 9886068a5610SStefano Zampini for (i = 0; i < N; i++) { 9887068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9888068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9889068a5610SStefano Zampini 9890068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9891068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9892068a5610SStefano Zampini B->sum += A->sum; 9893068a5610SStefano Zampini B->squaresum += A->squaresum; 9894068a5610SStefano Zampini B->count += A->count; 9895068a5610SStefano Zampini } 9896068a5610SStefano Zampini } 9897068a5610SStefano Zampini 9898068a5610SStefano Zampini /*@ 989943fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9900068a5610SStefano Zampini 990120f4b53cSBarry Smith Collective 99028261a58bSMatthew G. Knepley 9903068a5610SStefano Zampini Input Parameters: 9904a1cb98faSBarry Smith + dm - The `DMPLEX` object 990520f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9906a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9907a1cb98faSBarry Smith 9908a1cb98faSBarry Smith Level: developer 9909068a5610SStefano Zampini 991095eb5ee5SVaclav Hapla Notes: 991195eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 991295eb5ee5SVaclav Hapla 9913a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9914068a5610SStefano Zampini 99151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9916068a5610SStefano Zampini @*/ 9917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9918d71ae5a4SJacob Faibussowitsch { 9919068a5610SStefano Zampini DM dmCoarse; 992043fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 992143fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 992243fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 992343fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9924412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 992543fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9926068a5610SStefano Zampini 9927068a5610SStefano Zampini PetscFunctionBegin; 9928068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9929068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9930068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9931068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9932068a5610SStefano Zampini stats.count = 0; 9933068a5610SStefano Zampini 99349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 99359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 99369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 99379566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 99389566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 99399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9940412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9941068a5610SStefano Zampini PetscInt i; 9942068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9943068a5610SStefano Zampini 99449566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 994563a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 994643fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9947068a5610SStefano Zampini frobJ += J[i] * J[i]; 9948068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9949068a5610SStefano Zampini } 9950068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9951068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9952068a5610SStefano Zampini 9953068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9954068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9955068a5610SStefano Zampini stats.sum += cond; 9956068a5610SStefano Zampini stats.squaresum += cond2; 9957068a5610SStefano Zampini stats.count++; 99588261a58bSMatthew G. Knepley if (output && cond > limit) { 995943fa8764SMatthew G. Knepley PetscSection coordSection; 996043fa8764SMatthew G. Knepley Vec coordsLocal; 996143fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 996243fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 996343fa8764SMatthew G. Knepley 99649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 99659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 99669566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 996763a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 996843fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 996963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 997043fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 99719566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 99729566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 997343fa8764SMatthew G. Knepley } 99749566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 997543fa8764SMatthew G. Knepley } 99769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 997743fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 997843fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 997943fa8764SMatthew G. Knepley 998043fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 998143fa8764SMatthew G. Knepley PetscReal len; 998243fa8764SMatthew G. Knepley 99839566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 998463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 998543fa8764SMatthew G. Knepley } 998643fa8764SMatthew G. Knepley } 99879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 99889566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 998943fa8764SMatthew G. Knepley } 9990068a5610SStefano Zampini } 99919566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9992068a5610SStefano Zampini 9993068a5610SStefano Zampini if (size > 1) { 9994068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9995068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9996068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9997068a5610SStefano Zampini MPI_Op statReduce; 9998068a5610SStefano Zampini 99999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 100009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 100019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 100029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 100039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 100049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 10005068a5610SStefano Zampini } else { 100069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 10007068a5610SStefano Zampini } 10008dd400576SPatrick Sanan if (rank == 0) { 10009068a5610SStefano Zampini count = globalStats.count; 10010068a5610SStefano Zampini min = globalStats.min; 10011068a5610SStefano Zampini max = globalStats.max; 10012068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 10013068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 10014068a5610SStefano Zampini } 10015068a5610SStefano Zampini 1001648a46eb9SPierre 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)); 100179566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 10018068a5610SStefano Zampini 100199566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 10020068a5610SStefano Zampini if (dmCoarse) { 10021068a5610SStefano Zampini PetscBool isplex; 10022068a5610SStefano Zampini 100239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 100241baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 10025068a5610SStefano Zampini } 100263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10027068a5610SStefano Zampini } 10028068a5610SStefano Zampini 10029f108dbd7SJacob Faibussowitsch /*@ 10030f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 10031f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 10032f108dbd7SJacob Faibussowitsch 1003320f4b53cSBarry Smith Collective 10034f108dbd7SJacob Faibussowitsch 10035f108dbd7SJacob Faibussowitsch Input Parameters: 10036a1cb98faSBarry Smith + dm - The `DMPLEX` object 10037a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 10038f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 10039f108dbd7SJacob Faibussowitsch 10040f108dbd7SJacob Faibussowitsch Output Parameters: 1004120f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 10042a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 10043f108dbd7SJacob Faibussowitsch 10044f108dbd7SJacob Faibussowitsch Options Database Keys: 10045a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 10046f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 10047f108dbd7SJacob Faibussowitsch 10048a1cb98faSBarry Smith Level: intermediate 10049a1cb98faSBarry Smith 10050f108dbd7SJacob Faibussowitsch Notes: 10051a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 10052f108dbd7SJacob Faibussowitsch 10053a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 10054f108dbd7SJacob Faibussowitsch 10055f108dbd7SJacob 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 10056f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 10057f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 10058f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 10059f108dbd7SJacob Faibussowitsch 10060f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 10061f108dbd7SJacob Faibussowitsch 10062a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 10063f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 10064f108dbd7SJacob Faibussowitsch 10065f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 10066f108dbd7SJacob Faibussowitsch 100671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 10068f108dbd7SJacob Faibussowitsch @*/ 10069ce78bad3SBarry Smith PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PeOp PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 10070d71ae5a4SJacob Faibussowitsch { 100716ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 100726ed19f2fSJacob Faibussowitsch PetscInt *idx; 100736ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 10074f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 100756ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 10076f108dbd7SJacob Faibussowitsch MPI_Comm comm; 10077f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 10078f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 10079f108dbd7SJacob Faibussowitsch IS glob; 10080f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 10081f108dbd7SJacob Faibussowitsch PetscViewer vwr; 10082f108dbd7SJacob Faibussowitsch 10083f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 10084f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10085ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 100864f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 100876bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 100889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 100899566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 1009063a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 100916ed19f2fSJacob Faibussowitsch { 100926ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 100936ed19f2fSJacob Faibussowitsch 100949566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 10095f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 10096f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 10097f108dbd7SJacob Faibussowitsch 100989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1009998921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 10100f108dbd7SJacob Faibussowitsch } 101016ed19f2fSJacob Faibussowitsch } 10102f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 101034f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 101049566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 101059566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 101069371c9d4SSatish Balay } else { 101079371c9d4SSatish Balay *OrthQualLabel = NULL; 101089371c9d4SSatish Balay } 101099566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 101109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 10111e2b8d0fcSMatthew G. Knepley PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, &glob)); 101129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 101139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 101149566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 101159566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 101169566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 101179566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 101189566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 101199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 101209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 101219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 101229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 101239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 101249566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 101259566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 101269566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 101276ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 101286ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 10129f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 10130f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 10131898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 10132f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 10133f108dbd7SJacob Faibussowitsch 101346ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 10135f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 10136f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 101379566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 101389566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 10139f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 101409566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 101416ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 101426ed19f2fSJacob Faibussowitsch PetscInt i; 101436ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 10144f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 10145f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 10146f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 10147f108dbd7SJacob Faibussowitsch 10148f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 10149f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 101509566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 10151f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 101526ed19f2fSJacob Faibussowitsch { 101536ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 101546ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 101556ed19f2fSJacob Faibussowitsch 101569566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 101579566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 101589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 101596ed19f2fSJacob Faibussowitsch } 10160f108dbd7SJacob Faibussowitsch 10161f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 10162f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 10163f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 10164f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 10165f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 10166addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 10167addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 10168addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 10169f108dbd7SJacob Faibussowitsch } 10170addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 10171addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 10172addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 10173f108dbd7SJacob Faibussowitsch 10174f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 10175f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 10176f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 10177f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 10178f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 10179f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 10180f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 10181f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 10182f108dbd7SJacob Faibussowitsch } 10183ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 10184ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 10185f108dbd7SJacob Faibussowitsch } 101869566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 101879566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 10188f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 101896ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 10190f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 101919566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 10192f108dbd7SJacob Faibussowitsch } 10193f108dbd7SJacob Faibussowitsch } 101949566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 101959566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 101969566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 101979566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 101989566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 10199648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 10200f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 102019566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 10202f108dbd7SJacob Faibussowitsch } 102039566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 10204648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&vwr)); 102059566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 102063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10207f108dbd7SJacob Faibussowitsch } 10208f108dbd7SJacob Faibussowitsch 10209d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 102101eb70e55SToby Isaac * interpolator construction */ 10211d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 10212d71ae5a4SJacob Faibussowitsch { 102131eb70e55SToby Isaac PetscSection section, newSection, gsection; 102141eb70e55SToby Isaac PetscSF sf; 102151eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 102161eb70e55SToby Isaac 102171eb70e55SToby Isaac PetscFunctionBegin; 102181eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102194f572ea9SToby Isaac PetscAssertPointer(odm, 2); 102209566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 102219566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 102225440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 102231eb70e55SToby Isaac if (!ghasConstraints) { 102249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 102251eb70e55SToby Isaac *odm = dm; 102263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102271eb70e55SToby Isaac } 102289566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 10229bb4b53efSMatthew G. Knepley PetscCall(DMCopyFields(dm, PETSC_DETERMINE, PETSC_DETERMINE, *odm)); 102309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 102319566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 10232eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 102339566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 102349566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 102353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102361eb70e55SToby Isaac } 102371eb70e55SToby Isaac 10238d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 10239d71ae5a4SJacob Faibussowitsch { 102401eb70e55SToby Isaac DM dmco, dmfo; 102411eb70e55SToby Isaac Mat interpo; 102421eb70e55SToby Isaac Vec rscale; 102431eb70e55SToby Isaac Vec cglobalo, clocal; 102441eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 102451eb70e55SToby Isaac PetscBool regular; 102461eb70e55SToby Isaac 102471eb70e55SToby Isaac PetscFunctionBegin; 102489566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 102499566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 102509566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 102519566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 102529566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 102539566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 102549566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 102559566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 102569566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 102579566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 102589566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 102599566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 102609566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 102619566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 102629566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 102639566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 102649566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 102659566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 102669566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 102679566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 102689566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 102699566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 102709566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 102719566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 102721eb70e55SToby Isaac *shift = fglobal; 102739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 102749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 102759566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 102769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 102779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 102789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 102799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 102809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 102813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102821eb70e55SToby Isaac } 102831eb70e55SToby Isaac 10284d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 10285d71ae5a4SJacob Faibussowitsch { 102861eb70e55SToby Isaac PetscObject shifto; 102871eb70e55SToby Isaac Vec shift; 102881eb70e55SToby Isaac 102891eb70e55SToby Isaac PetscFunctionBegin; 102901eb70e55SToby Isaac if (!interp) { 102911eb70e55SToby Isaac Vec rscale; 102921eb70e55SToby Isaac 102939566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 102949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 102951eb70e55SToby Isaac } else { 102969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 102971eb70e55SToby Isaac } 102989566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 102991eb70e55SToby Isaac if (!shifto) { 103009566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 103019566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 103021eb70e55SToby Isaac shifto = (PetscObject)shift; 103039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 103041eb70e55SToby Isaac } 103051eb70e55SToby Isaac shift = (Vec)shifto; 103069566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 103079566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 103089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 103093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103101eb70e55SToby Isaac } 103111eb70e55SToby Isaac 10312bceba477SMatthew G. Knepley /* Pointwise interpolation 10313bceba477SMatthew G. Knepley Just code FEM for now 10314bceba477SMatthew G. Knepley u^f = I u^c 103154ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 103164ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 103174ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 10318bceba477SMatthew G. Knepley */ 10319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 10320d71ae5a4SJacob Faibussowitsch { 10321bceba477SMatthew G. Knepley PetscSection gsc, gsf; 10322bceba477SMatthew G. Knepley PetscInt m, n; 10323a063dac3SMatthew G. Knepley void *ctx; 1032468132eb9SMatthew G. Knepley DM cdm; 10325cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 10326bceba477SMatthew G. Knepley 10327bceba477SMatthew G. Knepley PetscFunctionBegin; 103289566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 103299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 103309566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 103319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 1033268132eb9SMatthew G. Knepley 103339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 103349566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 103359566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 103369566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 103379566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 1033868132eb9SMatthew G. Knepley 103399566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 103409566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 103419566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 103429566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 103439566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 103444db47ee9SStefano Zampini if (scaling) { 103455d1c2e58SMatthew G. Knepley /* Use naive scaling */ 103469566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 103474db47ee9SStefano Zampini } 103483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10349a063dac3SMatthew G. Knepley } 10350bceba477SMatthew G. Knepley 10351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 10352d71ae5a4SJacob Faibussowitsch { 103536dbf9973SLawrence Mitchell VecScatter ctx; 1035490748bafSMatthew G. Knepley 10355a063dac3SMatthew G. Knepley PetscFunctionBegin; 103569566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 103579566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 103589566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 103593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10360bceba477SMatthew G. Knepley } 10361bceba477SMatthew G. Knepley 10362d71ae5a4SJacob 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[]) 10363d71ae5a4SJacob Faibussowitsch { 10364a102dd69SStefano Zampini const PetscInt f = (PetscInt)PetscRealPart(constants[numConstants]); 10365a102dd69SStefano Zampini const PetscInt Nc = uOff[f + 1] - uOff[f]; 10366a102dd69SStefano Zampini for (PetscInt c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 103673e9753d6SMatthew G. Knepley } 103683e9753d6SMatthew G. Knepley 103691898fd5cSMatthew 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) 103701898fd5cSMatthew 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[]) 103711898fd5cSMatthew G. Knepley { 103721898fd5cSMatthew G. Knepley for (PetscInt c = 0; c < dim; ++c) g1[c * dim + c] = 1.0; 103731898fd5cSMatthew G. Knepley } 103741898fd5cSMatthew G. Knepley 103758e9849d2SStefano Zampini PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *lmass, Vec *mass) 10376d71ae5a4SJacob Faibussowitsch { 10377b4937a87SMatthew G. Knepley DM dmc; 10378b4937a87SMatthew G. Knepley PetscDS ds; 10379b4937a87SMatthew G. Knepley Vec ones, locmass; 10380b4937a87SMatthew G. Knepley IS cellIS; 10381b4937a87SMatthew G. Knepley PetscFormKey key; 10382b4937a87SMatthew G. Knepley PetscInt depth; 10383b4937a87SMatthew G. Knepley 10384b4937a87SMatthew G. Knepley PetscFunctionBegin; 103859566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 103869566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 103879566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 10388a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 103898e9849d2SStefano Zampini if (mass) PetscCall(DMCreateGlobalVector(dm, mass)); 103908e9849d2SStefano Zampini if (lmass) PetscCall(DMCreateLocalVector(dm, &locmass)); 103918e9849d2SStefano Zampini else PetscCall(DMGetLocalVector(dm, &locmass)); 103928e9849d2SStefano Zampini PetscCall(DMGetLocalVector(dm, &ones)); 103938e9849d2SStefano Zampini PetscCall(DMPlexGetDepth(dm, &depth)); 103948e9849d2SStefano Zampini PetscCall(DMGetStratumIS(dm, "depth", depth, &cellIS)); 103959566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 103969566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10397b4937a87SMatthew G. Knepley key.label = NULL; 10398b4937a87SMatthew G. Knepley key.value = 0; 10399b4937a87SMatthew G. Knepley key.field = 0; 10400b4937a87SMatthew G. Knepley key.part = 0; 10401754e4fbaSMatthew G. Knepley PetscCall(DMPlexComputeJacobianActionByKey(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 104029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 104038e9849d2SStefano Zampini if (mass) { 104048e9849d2SStefano Zampini PetscCall(DMLocalToGlobalBegin(dm, locmass, ADD_VALUES, *mass)); 104058e9849d2SStefano Zampini PetscCall(DMLocalToGlobalEnd(dm, locmass, ADD_VALUES, *mass)); 104068e9849d2SStefano Zampini } 104078e9849d2SStefano Zampini PetscCall(DMRestoreLocalVector(dm, &ones)); 104088e9849d2SStefano Zampini if (lmass) *lmass = locmass; 104098e9849d2SStefano Zampini else PetscCall(DMRestoreLocalVector(dm, &locmass)); 104109566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 104113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10412b4937a87SMatthew G. Knepley } 10413b4937a87SMatthew G. Knepley 10414d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10415d71ae5a4SJacob Faibussowitsch { 10416bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10417bd041c0cSMatthew G. Knepley PetscInt m, n; 10418bd041c0cSMatthew G. Knepley void *ctx; 10419bd041c0cSMatthew G. Knepley DM cdm; 10420bd041c0cSMatthew G. Knepley PetscBool regular; 10421bd041c0cSMatthew G. Knepley 10422bd041c0cSMatthew G. Knepley PetscFunctionBegin; 104233e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 104243e9753d6SMatthew G. Knepley DM dmc; 104253e9753d6SMatthew G. Knepley PetscDS ds; 10426b4937a87SMatthew G. Knepley PetscWeakForm wf; 104273e9753d6SMatthew G. Knepley Vec u; 104283e9753d6SMatthew G. Knepley IS cellIS; 1042906ad1575SMatthew G. Knepley PetscFormKey key; 104303e9753d6SMatthew G. Knepley PetscInt depth; 104313e9753d6SMatthew G. Knepley 104329566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 104339566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 104349566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 104359566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 104369566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 10437a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 104389566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 104398d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 104409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 104419566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 104429566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 104436528b96dSMatthew G. Knepley key.label = NULL; 104446528b96dSMatthew G. Knepley key.value = 0; 104456528b96dSMatthew G. Knepley key.field = 0; 1044606ad1575SMatthew G. Knepley key.part = 0; 10447754e4fbaSMatthew G. Knepley PetscCall(DMPlexComputeJacobianByKey(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 104489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 104498d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 104509566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 104513e9753d6SMatthew G. Knepley } else { 104529566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 104539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 104549566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 104559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10456bd041c0cSMatthew G. Knepley 104579566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 104589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 104599566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 104609566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10461bd041c0cSMatthew G. Knepley 104629566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 104639566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 104649566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 104659566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 104663e9753d6SMatthew G. Knepley } 104679566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 104683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10469bd041c0cSMatthew G. Knepley } 10470bd041c0cSMatthew G. Knepley 104711898fd5cSMatthew G. Knepley PetscErrorCode DMCreateGradientMatrix_Plex(DM dmc, DM dmr, Mat *derv) 104721898fd5cSMatthew G. Knepley { 104731898fd5cSMatthew G. Knepley PetscSection gsc, gsf; 104741898fd5cSMatthew G. Knepley PetscInt m, n; 104751898fd5cSMatthew G. Knepley void *ctx; 104761898fd5cSMatthew G. Knepley 104771898fd5cSMatthew G. Knepley PetscFunctionBegin; 104781898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dmr, &gsf)); 104791898fd5cSMatthew G. Knepley PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 104801898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dmc, &gsc)); 104811898fd5cSMatthew G. Knepley PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 104821898fd5cSMatthew G. Knepley 104831898fd5cSMatthew G. Knepley PetscCall(MatCreate(PetscObjectComm((PetscObject)dmc), derv)); 104841898fd5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*derv, "Plex Derivative Matrix")); 104851898fd5cSMatthew G. Knepley PetscCall(MatSetSizes(*derv, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 104861898fd5cSMatthew G. Knepley PetscCall(MatSetType(*derv, dmc->mattype)); 104871898fd5cSMatthew G. Knepley 104881898fd5cSMatthew G. Knepley PetscCall(DMGetApplicationContext(dmr, &ctx)); 104891898fd5cSMatthew G. Knepley { 104901898fd5cSMatthew G. Knepley DM ndmr; 104911898fd5cSMatthew G. Knepley PetscDS ds; 104921898fd5cSMatthew G. Knepley PetscWeakForm wf; 104931898fd5cSMatthew G. Knepley Vec u; 104941898fd5cSMatthew G. Knepley IS cellIS; 104951898fd5cSMatthew G. Knepley PetscFormKey key; 104961898fd5cSMatthew G. Knepley PetscInt depth, Nf; 104971898fd5cSMatthew G. Knepley 104981898fd5cSMatthew G. Knepley PetscCall(DMClone(dmr, &ndmr)); 104991898fd5cSMatthew G. Knepley PetscCall(DMCopyDisc(dmr, ndmr)); 105001898fd5cSMatthew G. Knepley PetscCall(DMGetDS(ndmr, &ds)); 105011898fd5cSMatthew G. Knepley PetscCall(PetscDSGetWeakForm(ds, &wf)); 105021898fd5cSMatthew G. Knepley PetscCall(PetscWeakFormClear(wf)); 105031898fd5cSMatthew G. Knepley PetscCall(PetscDSGetNumFields(ds, &Nf)); 105041898fd5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, NULL, g1_identity_private, NULL, NULL)); 105051898fd5cSMatthew G. Knepley PetscCall(DMGetLocalVector(ndmr, &u)); 105061898fd5cSMatthew G. Knepley PetscCall(DMPlexGetDepth(ndmr, &depth)); 105071898fd5cSMatthew G. Knepley PetscCall(DMGetStratumIS(ndmr, "depth", depth, &cellIS)); 105081898fd5cSMatthew G. Knepley PetscCall(MatZeroEntries(*derv)); 105091898fd5cSMatthew G. Knepley key.label = NULL; 105101898fd5cSMatthew G. Knepley key.value = 0; 105111898fd5cSMatthew G. Knepley key.field = 0; 105121898fd5cSMatthew G. Knepley key.part = 0; 105131898fd5cSMatthew G. Knepley PetscCall(DMPlexComputeJacobianByKeyGeneral(ndmr, dmc, key, cellIS, 0.0, 0.0, u, NULL, *derv, *derv, NULL)); 105141898fd5cSMatthew G. Knepley PetscCall(ISDestroy(&cellIS)); 105151898fd5cSMatthew G. Knepley PetscCall(DMRestoreLocalVector(ndmr, &u)); 105161898fd5cSMatthew G. Knepley PetscCall(DMDestroy(&ndmr)); 105171898fd5cSMatthew G. Knepley } 105181898fd5cSMatthew G. Knepley PetscCall(MatViewFromOptions(*derv, NULL, "-gradient_mat_view")); 105191898fd5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 105201898fd5cSMatthew G. Knepley } 105211898fd5cSMatthew G. Knepley 105220aef6b92SMatthew G. Knepley /*@ 105230aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 105240aef6b92SMatthew G. Knepley 105250aef6b92SMatthew G. Knepley Input Parameter: 10526a1cb98faSBarry Smith . dm - The `DMPLEX` object 105270aef6b92SMatthew G. Knepley 105280aef6b92SMatthew G. Knepley Output Parameter: 105290aef6b92SMatthew G. Knepley . regular - The flag 105300aef6b92SMatthew G. Knepley 105310aef6b92SMatthew G. Knepley Level: intermediate 105320aef6b92SMatthew G. Knepley 105331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 105340aef6b92SMatthew G. Knepley @*/ 10535d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10536d71ae5a4SJacob Faibussowitsch { 105370aef6b92SMatthew G. Knepley PetscFunctionBegin; 105380aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105394f572ea9SToby Isaac PetscAssertPointer(regular, 2); 105400aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 105413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105420aef6b92SMatthew G. Knepley } 105430aef6b92SMatthew G. Knepley 105440aef6b92SMatthew G. Knepley /*@ 105450aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 105460aef6b92SMatthew G. Knepley 105470aef6b92SMatthew G. Knepley Input Parameters: 10548a1cb98faSBarry Smith + dm - The `DMPLEX` object 105490aef6b92SMatthew G. Knepley - regular - The flag 105500aef6b92SMatthew G. Knepley 105510aef6b92SMatthew G. Knepley Level: intermediate 105520aef6b92SMatthew G. Knepley 105531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 105540aef6b92SMatthew G. Knepley @*/ 10555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10556d71ae5a4SJacob Faibussowitsch { 105570aef6b92SMatthew G. Knepley PetscFunctionBegin; 105580aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105590aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 105603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105610aef6b92SMatthew G. Knepley } 105620aef6b92SMatthew G. Knepley 10563a68b90caSToby Isaac /*@ 10564f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10565a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10566a68b90caSToby Isaac 10567a1cb98faSBarry Smith Not Collective 10568a68b90caSToby Isaac 10569f899ff85SJose E. Roman Input Parameter: 10570a1cb98faSBarry Smith . dm - The `DMPLEX` object 10571a68b90caSToby Isaac 10572a68b90caSToby Isaac Output Parameters: 1057320f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1057420f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10575a68b90caSToby Isaac 10576a68b90caSToby Isaac Level: intermediate 10577a68b90caSToby Isaac 105781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10579a68b90caSToby Isaac @*/ 10580ce78bad3SBarry Smith PetscErrorCode DMPlexGetAnchors(DM dm, PeOp PetscSection *anchorSection, PeOp IS *anchorIS) 10581d71ae5a4SJacob Faibussowitsch { 10582a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10583a68b90caSToby Isaac 10584a68b90caSToby Isaac PetscFunctionBegin; 10585a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105869566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10587a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10588a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 105893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10590a68b90caSToby Isaac } 10591a68b90caSToby Isaac 10592a68b90caSToby Isaac /*@ 10593a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10594a68b90caSToby Isaac 1059520f4b53cSBarry Smith Collective 10596a68b90caSToby Isaac 10597a68b90caSToby Isaac Input Parameters: 10598a1cb98faSBarry Smith + dm - The `DMPLEX` object 10599a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10600a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10601a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10602a68b90caSToby Isaac 10603a68b90caSToby Isaac Level: intermediate 10604a68b90caSToby Isaac 10605a1cb98faSBarry Smith Notes: 10606a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10607a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10608a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10609a4e35b19SJacob Faibussowitsch 10610a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10611a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10612a1cb98faSBarry Smith 1061320f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10614a1cb98faSBarry Smith 106151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10616a68b90caSToby Isaac @*/ 10617d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10618d71ae5a4SJacob Faibussowitsch { 10619a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10620e228b242SToby Isaac PetscMPIInt result; 10621a68b90caSToby Isaac 10622a68b90caSToby Isaac PetscFunctionBegin; 10623a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10624e228b242SToby Isaac if (anchorSection) { 10625e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 106269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 106271dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10628e228b242SToby Isaac } 10629e228b242SToby Isaac if (anchorIS) { 10630e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 106319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 106321dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10633e228b242SToby Isaac } 10634a68b90caSToby Isaac 106359566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 106369566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10637a68b90caSToby Isaac plex->anchorSection = anchorSection; 10638a68b90caSToby Isaac 106399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 106409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10641a68b90caSToby Isaac plex->anchorIS = anchorIS; 10642a68b90caSToby Isaac 10643cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10644a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10645a68b90caSToby Isaac const PetscInt *anchors; 10646a68b90caSToby Isaac 106479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 106489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 106499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10650a68b90caSToby Isaac for (a = 0; a < size; a++) { 10651a68b90caSToby Isaac PetscInt p; 10652a68b90caSToby Isaac 10653a68b90caSToby Isaac p = anchors[a]; 10654a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10655a68b90caSToby Isaac PetscInt dof; 10656a68b90caSToby Isaac 106579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10658a68b90caSToby Isaac if (dof) { 106599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1066063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10661a68b90caSToby Isaac } 10662a68b90caSToby Isaac } 10663a68b90caSToby Isaac } 106649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10665a68b90caSToby Isaac } 10666f7c74593SToby Isaac /* reset the generic constraints */ 106679566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 106683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10669a68b90caSToby Isaac } 10670a68b90caSToby Isaac 10671d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10672d71ae5a4SJacob Faibussowitsch { 10673f7c74593SToby Isaac PetscSection anchorSection; 106746995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10675a68b90caSToby Isaac 10676a68b90caSToby Isaac PetscFunctionBegin; 10677a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 106789566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 106799566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 106809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 106816995de1eSToby Isaac if (numFields) { 10682719ab38cSToby Isaac PetscInt f; 106839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10684719ab38cSToby Isaac 10685719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10686719ab38cSToby Isaac PetscInt numComp; 10687719ab38cSToby Isaac 106889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 106899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10690719ab38cSToby Isaac } 106916995de1eSToby Isaac } 106929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 106939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 106946995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 106956995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 106966995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 106979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10698a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 106999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10700a68b90caSToby Isaac if (dof) { 107019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 107029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10703a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 107049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 107059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10706a68b90caSToby Isaac } 10707a68b90caSToby Isaac } 10708a68b90caSToby Isaac } 107099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 107109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 107113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10712a68b90caSToby Isaac } 10713a68b90caSToby Isaac 10714d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10715d71ae5a4SJacob Faibussowitsch { 10716f7c74593SToby Isaac PetscSection aSec; 10717ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 107180ac89760SToby Isaac const PetscInt *anchors; 107190ac89760SToby Isaac PetscInt numFields, f; 1072066ad2231SToby Isaac IS aIS; 10721e19f7ee6SMark Adams MatType mtype; 10722e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 107230ac89760SToby Isaac 107240ac89760SToby Isaac PetscFunctionBegin; 107250ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 107269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 107279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 107289566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 107299566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 107309566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 107319566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 107329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 107339566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10734e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10735e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10736e19f7ee6SMark Adams else mtype = MATSEQAIJ; 107379566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 107389566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 107399566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 107406995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 107419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 107429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 107439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 107440ac89760SToby Isaac i[0] = 0; 107459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 107460ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10747f19733c5SToby Isaac PetscInt rDof, rOff, r; 10748f19733c5SToby Isaac 107499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10750f19733c5SToby Isaac if (!rDof) continue; 107519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 107520ac89760SToby Isaac if (numFields) { 107530ac89760SToby Isaac for (f = 0; f < numFields; f++) { 107540ac89760SToby Isaac annz = 0; 10755f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10756f19733c5SToby Isaac a = anchors[rOff + r]; 10757ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 107590ac89760SToby Isaac annz += aDof; 107600ac89760SToby Isaac } 107619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 107629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10763ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 107640ac89760SToby Isaac } 107652f7452b8SBarry Smith } else { 107660ac89760SToby Isaac annz = 0; 107679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 107680ac89760SToby Isaac for (q = 0; q < dof; q++) { 10769ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10770ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 107720ac89760SToby Isaac annz += aDof; 107730ac89760SToby Isaac } 107749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 107759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10776ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 107770ac89760SToby Isaac } 107780ac89760SToby Isaac } 107790ac89760SToby Isaac nnz = i[m]; 107809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 107810ac89760SToby Isaac offset = 0; 107820ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 107830ac89760SToby Isaac if (numFields) { 107840ac89760SToby Isaac for (f = 0; f < numFields; f++) { 107859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 107860ac89760SToby Isaac for (q = 0; q < dof; q++) { 107870ac89760SToby Isaac PetscInt rDof, rOff, r; 107889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 107899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 107900ac89760SToby Isaac for (r = 0; r < rDof; r++) { 107910ac89760SToby Isaac PetscInt s; 107920ac89760SToby Isaac 107930ac89760SToby Isaac a = anchors[rOff + r]; 10794ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 107959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 107969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10797ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 107980ac89760SToby Isaac } 107990ac89760SToby Isaac } 108000ac89760SToby Isaac } 108012f7452b8SBarry Smith } else { 108029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 108030ac89760SToby Isaac for (q = 0; q < dof; q++) { 108040ac89760SToby Isaac PetscInt rDof, rOff, r; 108059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 108069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 108070ac89760SToby Isaac for (r = 0; r < rDof; r++) { 108080ac89760SToby Isaac PetscInt s; 108090ac89760SToby Isaac 108100ac89760SToby Isaac a = anchors[rOff + r]; 10811ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 108129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 108139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10814ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 108150ac89760SToby Isaac } 108160ac89760SToby Isaac } 108170ac89760SToby Isaac } 108180ac89760SToby Isaac } 108199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 108209566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 108219566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 108229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 108233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 108240ac89760SToby Isaac } 108250ac89760SToby Isaac 10826d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10827d71ae5a4SJacob Faibussowitsch { 10828f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10829f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1083066ad2231SToby Isaac Mat cMat; 1083166ad2231SToby Isaac 1083266ad2231SToby Isaac PetscFunctionBegin; 1083366ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 108349566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1083566ad2231SToby Isaac if (anchorSection) { 1083644a7f3ddSMatthew G. Knepley PetscInt Nf; 10837e228b242SToby Isaac 108389566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 108399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 108409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 108419566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 108429566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 108439566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 108449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 108459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1084666ad2231SToby Isaac } 108473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1084866ad2231SToby Isaac } 10849a93c429eSMatthew G. Knepley 10850d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10851d71ae5a4SJacob Faibussowitsch { 10852a93c429eSMatthew G. Knepley IS subis; 10853a93c429eSMatthew G. Knepley PetscSection section, subsection; 10854a93c429eSMatthew G. Knepley 10855a93c429eSMatthew G. Knepley PetscFunctionBegin; 108569566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1085728b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1085828b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10859a93c429eSMatthew G. Knepley /* Create subdomain */ 1086071f1c950SStefano Zampini PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, PetscObjectComm((PetscObject)dm), NULL, subdm)); 10861a93c429eSMatthew G. Knepley /* Create submodel */ 108629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 108639566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 108649566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 108659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 108669566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10867a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10868a93c429eSMatthew G. Knepley if (is) { 10869a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10870a93c429eSMatthew G. Knepley IS spIS; 10871a93c429eSMatthew G. Knepley const PetscInt *spmap; 10872a93c429eSMatthew G. Knepley PetscInt *subIndices; 10873a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10874a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10875a93c429eSMatthew G. Knepley 108769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 108779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 108789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 108799566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 108809566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 108819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10882a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10883a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10884a93c429eSMatthew G. Knepley 108859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10886a93c429eSMatthew G. Knepley if (gdof > 0) { 10887a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10888a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10889a93c429eSMatthew G. Knepley 108909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 108919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10892a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10893a93c429eSMatthew G. Knepley } 10894a93c429eSMatthew G. Knepley subSize += pSubSize; 10895a93c429eSMatthew G. Knepley if (pSubSize) { 10896a93c429eSMatthew G. Knepley if (bs < 0) { 10897a93c429eSMatthew G. Knepley bs = pSubSize; 10898a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10899a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10900a93c429eSMatthew G. Knepley bs = 1; 10901a93c429eSMatthew G. Knepley } 10902a93c429eSMatthew G. Knepley } 10903a93c429eSMatthew G. Knepley } 10904a93c429eSMatthew G. Knepley } 10905a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 109061690c2aeSBarry Smith bsLocal[0] = bs < 0 ? PETSC_INT_MAX : bs; 109079371c9d4SSatish Balay bsLocal[1] = bs; 109089566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 109099371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 109109371c9d4SSatish Balay bs = 1; 109119371c9d4SSatish Balay } else { 109129371c9d4SSatish Balay bs = bsMinMax[0]; 109139371c9d4SSatish Balay } 109149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10915a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10916a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10917a93c429eSMatthew G. Knepley 109189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10919a93c429eSMatthew G. Knepley if (gdof > 0) { 10920a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10921a93c429eSMatthew G. Knepley 109229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10923a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10924a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10925a93c429eSMatthew G. Knepley 10926a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10927a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 109289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 109299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10930a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10931a93c429eSMatthew G. Knepley } 109329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 109339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10934ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10935a93c429eSMatthew G. Knepley } 10936a93c429eSMatthew G. Knepley } 10937a93c429eSMatthew G. Knepley } 109389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 109399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10940a93c429eSMatthew G. Knepley if (bs > 1) { 10941a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10942a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10943a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10944a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 109459371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 109469371c9d4SSatish Balay set = 0; 109479371c9d4SSatish Balay break; 109489371c9d4SSatish Balay } 10949a93c429eSMatthew G. Knepley } 10950a93c429eSMatthew G. Knepley } 109519566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10952a93c429eSMatthew G. Knepley } 109534758e3ceSMatthew G. Knepley // Attach nullspace 109544758e3ceSMatthew G. Knepley if (dm->nullspaceConstructors) { 10955a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10956a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10957a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10958a93c429eSMatthew G. Knepley } 10959a93c429eSMatthew G. Knepley if (f < Nf) { 10960a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 109619566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 109626823f3c5SBlaise Bourdin 109639566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 109649566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10965a93c429eSMatthew G. Knepley } 10966a93c429eSMatthew G. Knepley } 109674758e3ceSMatthew G. Knepley } 109683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10969a93c429eSMatthew G. Knepley } 10970c0f0dcc3SMatthew G. Knepley 10971c0f0dcc3SMatthew G. Knepley /*@ 10972c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10973c0f0dcc3SMatthew G. Knepley 10974a1cb98faSBarry Smith Input Parameters: 10975a1cb98faSBarry Smith + dm - The `DM` 109762a8381b2SBarry Smith - unused - unused argument 10977a1cb98faSBarry Smith 10978a1cb98faSBarry Smith Options Database Key: 10979a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10980c0f0dcc3SMatthew G. Knepley 10981c0f0dcc3SMatthew G. Knepley Level: developer 10982c0f0dcc3SMatthew G. Knepley 109831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10984c0f0dcc3SMatthew G. Knepley @*/ 109852a8381b2SBarry Smith PetscErrorCode DMPlexMonitorThroughput(DM dm, void *unused) 10986d71ae5a4SJacob Faibussowitsch { 10987b665b14eSToby Isaac PetscLogHandler default_handler; 10988b665b14eSToby Isaac 109892611ad71SToby Isaac PetscFunctionBegin; 109902611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10991b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10992b665b14eSToby Isaac if (default_handler) { 10993c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10994c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10995835f2295SStefano Zampini PetscLogDouble cellRate, flopRate; 10996c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10997c0f0dcc3SMatthew G. Knepley const char *name; 10998c0f0dcc3SMatthew G. Knepley 109999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 110009566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 110019566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 110029566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 11003b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 11004c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 11005c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 11006c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 11007835f2295SStefano 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)); 110082611ad71SToby Isaac } else { 11009b665b14eSToby 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."); 110102611ad71SToby Isaac } 110113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11012c0f0dcc3SMatthew G. Knepley } 11013