1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11552f7358SJed Brown 12552f7358SJed Brown /* Logging support */ 1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad; 14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 15552f7358SJed Brown 16f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 18f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 19f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 20f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 21f39ec787SMatthew G. Knepley "volume = {38},\n" 22f39ec787SMatthew G. Knepley "number = {5},\n" 23f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 24f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 25f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 26f39ec787SMatthew G. Knepley "year = {2016},\n" 27f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 28f39ec787SMatthew G. Knepley 295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 30552f7358SJed Brown 31e5337592SStefano Zampini /*@ 329318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 339318fe57SMatthew G. Knepley 349318fe57SMatthew G. Knepley Input Parameter: 35a1cb98faSBarry Smith . dm - The `DMPLEX` object 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley Output Parameter: 389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley Level: intermediate 419318fe57SMatthew G. Knepley 42a1cb98faSBarry Smith Note: 43a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 44a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 45a1cb98faSBarry Smith 461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 479318fe57SMatthew G. Knepley @*/ 48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 49d71ae5a4SJacob Faibussowitsch { 509318fe57SMatthew G. Knepley DMPolytopeType ct; 519318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 529318fe57SMatthew G. Knepley 539318fe57SMatthew G. Knepley PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 559371c9d4SSatish Balay if (cEnd <= cStart) { 569371c9d4SSatish Balay *simplex = PETSC_FALSE; 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589371c9d4SSatish Balay } 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 609318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629318fe57SMatthew G. Knepley } 639318fe57SMatthew G. Knepley 649318fe57SMatthew G. Knepley /*@ 65412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 66e5337592SStefano Zampini 67d8d19677SJose E. Roman Input Parameters: 68a1cb98faSBarry Smith + dm - The `DMPLEX` object 69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 70e5337592SStefano Zampini 71e5337592SStefano Zampini Output Parameters: 72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7340196513SBarry Smith - cEnd - The upper bound on "normal" cells 74e5337592SStefano Zampini 75412e9a14SMatthew G. Knepley Level: developer 76e5337592SStefano Zampini 77a1cb98faSBarry Smith Note: 785ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 79a1cb98faSBarry Smith 802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 81e5337592SStefano Zampini @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 83d71ae5a4SJacob Faibussowitsch { 845ae96e2bSMatthew G. Knepley DMLabel ctLabel; 855ae96e2bSMatthew G. Knepley IS valueIS; 865ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 875ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 88e5337592SStefano Zampini 89e5337592SStefano Zampini PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 915ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 925ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 935ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 945ae96e2bSMatthew G. Knepley if (!Nct) cS = cE = 0; 955ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 96c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 975ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 985ae96e2bSMatthew G. Knepley 995ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1005ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1015ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1025ae96e2bSMatthew G. Knepley break; 1035ae96e2bSMatthew G. Knepley } 104c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1055ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1065ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1075ae96e2bSMatthew G. Knepley // Check that a point has the right height 1085ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1095ae96e2bSMatthew G. Knepley if (ht != height) continue; 1105ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1115ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1125ae96e2bSMatthew G. Knepley } 1135ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 114695799ffSMatthew G. Knepley // Reset label for fast lookup 115695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 116412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 117412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119e5337592SStefano Zampini } 120e5337592SStefano Zampini 1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1229c600e38SMatt McGurn { 1239c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1249c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1259c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1269c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1279c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1289c600e38SMatt McGurn 1299c600e38SMatt McGurn PetscFunctionBegin; 1309c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1319c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1329c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1339c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1349c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1359c600e38SMatt McGurn if (field >= 0) { 1369c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1379c600e38SMatt McGurn } else { 1389c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1399c600e38SMatt McGurn } 1409c600e38SMatt McGurn 1419c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1429c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1439c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1449c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1459c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1469c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1479c600e38SMatt McGurn PetscInt dep; 1489c600e38SMatt McGurn 1499c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1509c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1519c600e38SMatt McGurn if (pStart >= 0) { 1529c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1539c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1549c600e38SMatt McGurn } 1559c600e38SMatt McGurn if (field >= 0) { 1569c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1579c600e38SMatt McGurn } else { 1589c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1599c600e38SMatt McGurn } 1609c600e38SMatt McGurn } 1619c600e38SMatt McGurn 1629c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1639c600e38SMatt McGurn *types = 0; 1649c600e38SMatt McGurn 1659c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1669c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1679c600e38SMatt McGurn } 1689c600e38SMatt McGurn 1699c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1709c600e38SMatt McGurn t = 0; 1719c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1729c600e38SMatt McGurn sStart[t] = vStart; 1739c600e38SMatt McGurn sEnd[t] = vEnd; 1749c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1759c600e38SMatt McGurn ++t; 1769c600e38SMatt McGurn } 1779c600e38SMatt McGurn 1789c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1799c600e38SMatt McGurn if (globalvcdof[c]) { 1809c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1819c600e38SMatt McGurn 1829c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1839c600e38SMatt McGurn sStart[t] = cStart; 1849c600e38SMatt McGurn sEnd[t] = cEnd; 1859c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1869c600e38SMatt McGurn ++t; 1879c600e38SMatt McGurn } 1889c600e38SMatt McGurn } 1899c600e38SMatt McGurn 1904ad8454bSPierre Jolivet if (!*types) { 1919c600e38SMatt McGurn if (field >= 0) { 1929c600e38SMatt McGurn const char *fieldname; 1939c600e38SMatt McGurn 1949c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1959c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1969c600e38SMatt McGurn } else { 1979c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 1989c600e38SMatt McGurn } 1999c600e38SMatt McGurn } 2009c600e38SMatt McGurn 2019c600e38SMatt McGurn *ssStart = sStart; 2029c600e38SMatt McGurn *ssEnd = sEnd; 2039c600e38SMatt McGurn *sft = ft; 2049c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2059c600e38SMatt McGurn } 2069c600e38SMatt McGurn 2079c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2089c600e38SMatt McGurn { 2099c600e38SMatt McGurn PetscFunctionBegin; 2109c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2119c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2129c600e38SMatt McGurn } 2139c600e38SMatt McGurn 214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 215d71ae5a4SJacob Faibussowitsch { 216412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 217a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2187e42fee7SMatthew G. Knepley 2197e42fee7SMatthew G. Knepley PetscFunctionBegin; 220e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2257e42fee7SMatthew G. Knepley if (field >= 0) { 2269566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2279566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2287e42fee7SMatthew G. Knepley } else { 2299566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2309566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2317e42fee7SMatthew G. Knepley } 232712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 233a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2347e42fee7SMatthew G. Knepley *sStart = vStart; 2357e42fee7SMatthew G. Knepley *sEnd = vEnd; 236f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2377e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 238a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2397e42fee7SMatthew G. Knepley *sStart = cStart; 2407e42fee7SMatthew G. Knepley *sEnd = cEnd; 241f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2427e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 243e630c359SToby Isaac } else { 244e630c359SToby Isaac if (field >= 0) { 245e630c359SToby Isaac const char *fieldname; 246e630c359SToby Isaac 2479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 24863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 249e630c359SToby Isaac } else { 25063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 251e630c359SToby Isaac } 252e630c359SToby Isaac } 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2547e42fee7SMatthew G. Knepley } 2557e42fee7SMatthew G. Knepley 2566913077dSMatthew G. Knepley /*@ 2576913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2586913077dSMatthew G. Knepley 25920f4b53cSBarry Smith Collective 2606913077dSMatthew G. Knepley 2616913077dSMatthew G. Knepley Input Parameters: 262a1cb98faSBarry Smith + dm - The `DMPLEX` object 2636913077dSMatthew G. Knepley . n - The number of vectors 2646913077dSMatthew G. Knepley . u - The array of local vectors 265a1cb98faSBarry Smith - viewer - The `PetscViewer` 2666913077dSMatthew G. Knepley 2676913077dSMatthew G. Knepley Level: advanced 2686913077dSMatthew G. Knepley 2691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2706913077dSMatthew G. Knepley @*/ 271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 272d71ae5a4SJacob Faibussowitsch { 2736913077dSMatthew G. Knepley PetscDS ds; 2746913077dSMatthew G. Knepley PetscDraw draw = NULL; 2756913077dSMatthew G. Knepley PetscDrawLG lg; 2766913077dSMatthew G. Knepley Vec coordinates; 2776913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2786913077dSMatthew G. Knepley PetscReal *vals; 2796913077dSMatthew G. Knepley PetscInt *Nc; 2806913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2816913077dSMatthew G. Knepley char **names; 2826913077dSMatthew G. Knepley 2836913077dSMatthew G. Knepley PetscFunctionBegin; 2849566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2869566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2886913077dSMatthew G. Knepley 2899566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2903ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2926913077dSMatthew G. Knepley 2939566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2946913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2956913077dSMatthew G. Knepley const char *vname; 2966913077dSMatthew G. Knepley 2979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 2986913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 2996913077dSMatthew G. Knepley PetscObject disc; 3006913077dSMatthew G. Knepley const char *fname; 3016913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3026913077dSMatthew G. Knepley 3039566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3046913077dSMatthew G. Knepley /* TODO Create names for components */ 3056913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 307c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 308c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 309c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3109566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3116913077dSMatthew G. Knepley } 3126913077dSMatthew G. Knepley } 3136913077dSMatthew G. Knepley } 3149566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3156913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3199566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3206913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3216913077dSMatthew G. Knepley PetscScalar *x, *svals; 3226913077dSMatthew G. Knepley 3239566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3246913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3259566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3266913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3276913077dSMatthew G. Knepley } 3289566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3296913077dSMatthew G. Knepley } 3309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3319566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3329566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3339566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3346913077dSMatthew G. Knepley 3359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3386913077dSMatthew G. Knepley } 3396913077dSMatthew G. Knepley 340d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 341d71ae5a4SJacob Faibussowitsch { 3426913077dSMatthew G. Knepley DM dm; 3436913077dSMatthew G. Knepley 3446913077dSMatthew G. Knepley PetscFunctionBegin; 3459566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3469566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3486913077dSMatthew G. Knepley } 3496913077dSMatthew G. Knepley 350d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 351d71ae5a4SJacob Faibussowitsch { 352e412dcbdSMatthew G. Knepley DM dm; 353d1df6f1dSMatthew G. Knepley PetscSection s; 354e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 355e412dcbdSMatthew G. Knepley DM cdm; 356e412dcbdSMatthew G. Knepley PetscSection coordSection; 357e412dcbdSMatthew G. Knepley Vec coordinates; 358c9c77995SMatthew G. Knepley const PetscScalar *array; 359c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 360339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3616913077dSMatthew G. Knepley PetscBool flg; 362d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 363e412dcbdSMatthew G. Knepley const char *name; 364339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 365e412dcbdSMatthew G. Knepley 366e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3679566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3689566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3729566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3779566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 378e412dcbdSMatthew G. Knepley 3799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3809566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 381e412dcbdSMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 383c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3849566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 385e412dcbdSMatthew G. Knepley 386d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 387d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 388d1df6f1dSMatthew G. Knepley DM fdm = dm; 389d1df6f1dSMatthew G. Knepley Vec fv = v; 390d1df6f1dSMatthew G. Knepley IS fis; 391d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 392d1df6f1dSMatthew G. Knepley const char *fname; 393d1df6f1dSMatthew G. Knepley 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 396d1df6f1dSMatthew G. Knepley 3979566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 398ad540459SPierre Jolivet else prefix[0] = '\0'; 399d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4009566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4019566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4029566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4039566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 404d1df6f1dSMatthew G. Knepley } 405d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 406d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 407d1df6f1dSMatthew G. Knepley 4089566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 40963a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41063a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4119566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 412d1df6f1dSMatthew G. Knepley 413d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 415339e3443SMatthew G. Knepley if (!flg) { 4169566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4179566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 418d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 419339e3443SMatthew G. Knepley } 420c9c77995SMatthew G. Knepley 4219566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4229566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 423c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4249566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 425e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 42699a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 427c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 428c9c77995SMatthew G. Knepley PetscBool isDG; 429e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 430e412dcbdSMatthew G. Knepley 4319566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 432339e3443SMatthew G. Knepley if (a) { 433d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 434339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 435339e3443SMatthew G. Knepley } else { 436339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 437339e3443SMatthew G. Knepley PetscInt numVals, va; 438339e3443SMatthew G. Knepley 4399566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 44063a3b9bcSJacob Faibussowitsch PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals); 441d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 442d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 443d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 444d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 445339e3443SMatthew G. Knepley break; 446d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 447d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 448d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / (Nc * 2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp + numVals / (Nc * 2)]), vbound[0], vbound[1]); 449d1df6f1dSMatthew G. Knepley break; 450d71ae5a4SJacob Faibussowitsch default: 451d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 452339e3443SMatthew G. Knepley } 4539566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 454339e3443SMatthew G. Knepley } 455c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 456e412dcbdSMatthew G. Knepley switch (numCoords) { 457e412dcbdSMatthew G. Knepley case 6: 4589edc3542SMatthew Knepley case 12: /* Localized triangle */ 4599566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 460e412dcbdSMatthew G. Knepley break; 461e412dcbdSMatthew G. Knepley case 8: 4629edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 4639566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 4649566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0])); 465e412dcbdSMatthew G. Knepley break; 466d71ae5a4SJacob Faibussowitsch default: 467d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 468e412dcbdSMatthew G. Knepley } 469c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 470e412dcbdSMatthew G. Knepley } 4719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4729566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4739566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 475d1df6f1dSMatthew G. Knepley } 476d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4779566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 480d1df6f1dSMatthew G. Knepley } 481d1df6f1dSMatthew G. Knepley } 4823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 483e412dcbdSMatthew G. Knepley } 484e412dcbdSMatthew G. Knepley 485d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 486d71ae5a4SJacob Faibussowitsch { 4876913077dSMatthew G. Knepley DM dm; 4886913077dSMatthew G. Knepley PetscDraw draw; 4896913077dSMatthew G. Knepley PetscInt dim; 4906913077dSMatthew G. Knepley PetscBool isnull; 4916913077dSMatthew G. Knepley 4926913077dSMatthew G. Knepley PetscFunctionBegin; 4939566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4953ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4966913077dSMatthew G. Knepley 4979566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 4996913077dSMatthew G. Knepley switch (dim) { 500d71ae5a4SJacob Faibussowitsch case 1: 501d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 502d71ae5a4SJacob Faibussowitsch break; 503d71ae5a4SJacob Faibussowitsch case 2: 504d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 505d71ae5a4SJacob Faibussowitsch break; 506d71ae5a4SJacob Faibussowitsch default: 507d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5086913077dSMatthew G. Knepley } 5093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5106913077dSMatthew G. Knepley } 5116913077dSMatthew G. Knepley 512d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 513d71ae5a4SJacob Faibussowitsch { 514684b87d9SLisandro Dalcin DM dm; 515684b87d9SLisandro Dalcin Vec locv; 516684b87d9SLisandro Dalcin const char *name; 517684b87d9SLisandro Dalcin PetscSection section; 518684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 519e630c359SToby Isaac PetscInt numFields; 520684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 521684b87d9SLisandro Dalcin 522684b87d9SLisandro Dalcin PetscFunctionBegin; 5239566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5249566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5279566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 530e630c359SToby Isaac if (!numFields) { 5319566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5329566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 533e630c359SToby Isaac } else { 534e630c359SToby Isaac PetscInt f; 535e630c359SToby Isaac 536e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5379566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 538e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 541e630c359SToby Isaac } 5429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 543e630c359SToby Isaac } 5443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545684b87d9SLisandro Dalcin } 546684b87d9SLisandro Dalcin 547d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 548d71ae5a4SJacob Faibussowitsch { 549552f7358SJed Brown DM dm; 5505f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 551552f7358SJed Brown 552552f7358SJed Brown PetscFunctionBegin; 5539566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 55428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5595f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5605f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 561684b87d9SLisandro Dalcin PetscInt i, numFields; 562684b87d9SLisandro Dalcin PetscObject fe; 563ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 564684b87d9SLisandro Dalcin Vec locv = v; 565684b87d9SLisandro Dalcin const char *name; 566684b87d9SLisandro Dalcin PetscInt step; 567684b87d9SLisandro Dalcin PetscReal time; 568ef31f671SMatthew G. Knepley 5699566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 570684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5719566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5729371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5739371c9d4SSatish Balay fem = PETSC_TRUE; 5749371c9d4SSatish Balay break; 5759371c9d4SSatish Balay } 576ef31f671SMatthew G. Knepley } 577684b87d9SLisandro Dalcin if (fem) { 578798534f6SMatthew G. Knepley PetscObject isZero; 579798534f6SMatthew G. Knepley 5809566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5859566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5869566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 5879566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 588ef31f671SMatthew G. Knepley } 589552f7358SJed Brown if (isvtk) { 5909566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 591b136c2c9SMatthew G. Knepley } else if (ishdf5) { 592b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5939566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 594b136c2c9SMatthew G. Knepley #else 595b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 596b136c2c9SMatthew G. Knepley #endif 597f13a32a3SMatthew G. Knepley } else if (isdraw) { 5989566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 599684b87d9SLisandro Dalcin } else if (isglvis) { 6009566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6019566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6029566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6035f34f2dcSJed Brown } else if (iscgns) { 6045f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6055f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6065f34f2dcSJed Brown #else 6075f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6085f34f2dcSJed Brown #endif 609684b87d9SLisandro Dalcin } 610798534f6SMatthew G. Knepley if (fem) { 6119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6129566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 613798534f6SMatthew G. Knepley } 614552f7358SJed Brown } else { 615684b87d9SLisandro Dalcin PetscBool isseq; 616684b87d9SLisandro Dalcin 6179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6189566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6199566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 620552f7358SJed Brown } 6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 622552f7358SJed Brown } 623552f7358SJed Brown 624d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 625d71ae5a4SJacob Faibussowitsch { 626552f7358SJed Brown DM dm; 6275f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 628552f7358SJed Brown 629552f7358SJed Brown PetscFunctionBegin; 6309566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63128b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6365f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6385f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 639552f7358SJed Brown Vec locv; 640798534f6SMatthew G. Knepley PetscObject isZero; 641552f7358SJed Brown const char *name; 642552f7358SJed Brown 6439566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6469566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6489566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6509566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6529566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 653b136c2c9SMatthew G. Knepley } else if (ishdf5) { 654b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6559566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 656b136c2c9SMatthew G. Knepley #else 657b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 658b136c2c9SMatthew G. Knepley #endif 6596823f3c5SBlaise Bourdin } else if (isexodusii) { 6606823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6619566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6626823f3c5SBlaise Bourdin #else 6636823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6646823f3c5SBlaise Bourdin #endif 665552f7358SJed Brown } else { 666684b87d9SLisandro Dalcin PetscBool isseq; 667684b87d9SLisandro Dalcin 6689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6699566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6709566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 671552f7358SJed Brown } 6723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 673552f7358SJed Brown } 674552f7358SJed Brown 675d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 676d71ae5a4SJacob Faibussowitsch { 677d930f514SMatthew G. Knepley DM dm; 678d930f514SMatthew G. Knepley MPI_Comm comm; 679d930f514SMatthew G. Knepley PetscViewerFormat format; 680d930f514SMatthew G. Knepley Vec v; 681d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 682d930f514SMatthew G. Knepley 683d930f514SMatthew G. Knepley PetscFunctionBegin; 6849566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 6859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 68628b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6879566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 690d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 691a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 692a8ad634aSStefano Zampini /* this need a better fix */ 693a8ad634aSStefano Zampini if (dm->useNatural) { 694a8ad634aSStefano Zampini if (dm->sfNatural) { 695d930f514SMatthew G. Knepley const char *vecname; 696d930f514SMatthew G. Knepley PetscInt n, nroots; 697d930f514SMatthew G. Knepley 6989566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 6999566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 700d930f514SMatthew G. Knepley if (n == nroots) { 701f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7029566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7039566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 706d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 707d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 708a8ad634aSStefano Zampini } else v = originalv; 709a8ad634aSStefano Zampini } else v = originalv; 710a8ad634aSStefano Zampini 711d930f514SMatthew G. Knepley if (ishdf5) { 712d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7139566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 714d930f514SMatthew G. Knepley #else 715d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 716d930f514SMatthew G. Knepley #endif 717d930f514SMatthew G. Knepley } else if (isvtk) { 718d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 719d930f514SMatthew G. Knepley } else { 720d930f514SMatthew G. Knepley PetscBool isseq; 721d930f514SMatthew G. Knepley 7229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7239566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7249566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 725d930f514SMatthew G. Knepley } 726f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 728d930f514SMatthew G. Knepley } 729d930f514SMatthew G. Knepley 730d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 731d71ae5a4SJacob Faibussowitsch { 7322c40f234SMatthew G. Knepley DM dm; 7332c40f234SMatthew G. Knepley PetscBool ishdf5; 7342c40f234SMatthew G. Knepley 7352c40f234SMatthew G. Knepley PetscFunctionBegin; 7369566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 73728b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7392c40f234SMatthew G. Knepley if (ishdf5) { 7402c40f234SMatthew G. Knepley DM dmBC; 7412c40f234SMatthew G. Knepley Vec gv; 7422c40f234SMatthew G. Knepley const char *name; 7432c40f234SMatthew G. Knepley 7449566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7459566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7489566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7509566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7519566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7521baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7542c40f234SMatthew G. Knepley } 7552c40f234SMatthew G. Knepley 756d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 757d71ae5a4SJacob Faibussowitsch { 7582c40f234SMatthew G. Knepley DM dm; 7596823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7602c40f234SMatthew G. Knepley 7612c40f234SMatthew G. Knepley PetscFunctionBegin; 7629566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7662c40f234SMatthew G. Knepley if (ishdf5) { 767878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7689566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 769b136c2c9SMatthew G. Knepley #else 770b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 771878b459fSMatthew G. Knepley #endif 7726823f3c5SBlaise Bourdin } else if (isexodusii) { 7736823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7749566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7756823f3c5SBlaise Bourdin #else 7766823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7776823f3c5SBlaise Bourdin #endif 7781baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 780552f7358SJed Brown } 781552f7358SJed Brown 782d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 783d71ae5a4SJacob Faibussowitsch { 784d930f514SMatthew G. Knepley DM dm; 785d930f514SMatthew G. Knepley PetscViewerFormat format; 786d930f514SMatthew G. Knepley PetscBool ishdf5; 787d930f514SMatthew G. Knepley 788d930f514SMatthew G. Knepley PetscFunctionBegin; 7899566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 79028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 793d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 794a8ad634aSStefano Zampini if (dm->useNatural) { 795d930f514SMatthew G. Knepley if (dm->sfNatural) { 796d930f514SMatthew G. Knepley if (ishdf5) { 797d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 798d930f514SMatthew G. Knepley Vec v; 799d930f514SMatthew G. Knepley const char *vecname; 800d930f514SMatthew G. Knepley 801f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8049566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8059566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8069566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 807f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 808d930f514SMatthew G. Knepley #else 809d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 810d930f514SMatthew G. Knepley #endif 811d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 812d930f514SMatthew G. Knepley } 8131baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 814d930f514SMatthew G. Knepley } 8153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 816d930f514SMatthew G. Knepley } 817d930f514SMatthew G. Knepley 818d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 819d71ae5a4SJacob Faibussowitsch { 820731e8ddeSMatthew G. Knepley PetscSection coordSection; 821731e8ddeSMatthew G. Knepley Vec coordinates; 822ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 823731e8ddeSMatthew G. Knepley const char *name[4]; 824731e8ddeSMatthew G. Knepley const PetscScalar *a; 825731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 826731e8ddeSMatthew G. Knepley 827731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8359566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 836731e8ddeSMatthew G. Knepley name[0] = "vertex"; 837731e8ddeSMatthew G. Knepley name[1] = "edge"; 838731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 839731e8ddeSMatthew G. Knepley name[dim] = "cell"; 840731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 841731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 842ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 843731e8ddeSMatthew G. Knepley 8449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 84563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 848731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 849731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 850731e8ddeSMatthew G. Knepley 851731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 853731e8ddeSMatthew G. Knepley if (!dof) continue; 8549566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 85663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 857731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 859731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8609566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 862731e8ddeSMatthew G. Knepley } 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 864731e8ddeSMatthew G. Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 866731e8ddeSMatthew G. Knepley } 8679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 869731e8ddeSMatthew G. Knepley } 8709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 872731e8ddeSMatthew G. Knepley } 873731e8ddeSMatthew G. Knepley 8749371c9d4SSatish Balay typedef enum { 8759371c9d4SSatish Balay CS_CARTESIAN, 8769371c9d4SSatish Balay CS_POLAR, 8779371c9d4SSatish Balay CS_CYLINDRICAL, 8789371c9d4SSatish Balay CS_SPHERICAL 8799371c9d4SSatish Balay } CoordSystem; 88019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 88119ad8254SMatthew G. Knepley 882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 883d71ae5a4SJacob Faibussowitsch { 88419ad8254SMatthew G. Knepley PetscInt i; 88519ad8254SMatthew G. Knepley 88619ad8254SMatthew G. Knepley PetscFunctionBegin; 88719ad8254SMatthew G. Knepley if (dim > 3) { 8889566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 88919ad8254SMatthew G. Knepley } else { 890bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 89119ad8254SMatthew G. Knepley 89219ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 89319ad8254SMatthew G. Knepley switch (cs) { 8949371c9d4SSatish Balay case CS_CARTESIAN: 8959371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8969371c9d4SSatish Balay break; 89719ad8254SMatthew G. Knepley case CS_POLAR: 89863a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 89919ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90019ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90119ad8254SMatthew G. Knepley break; 90219ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 90363a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 90419ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90519ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90619ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 90719ad8254SMatthew G. Knepley break; 90819ad8254SMatthew G. Knepley case CS_SPHERICAL: 90963a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 91019ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 91119ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 91219ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 91319ad8254SMatthew G. Knepley break; 91419ad8254SMatthew G. Knepley } 9159566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 91619ad8254SMatthew G. Knepley } 9173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91819ad8254SMatthew G. Knepley } 91919ad8254SMatthew G. Knepley 920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 921d71ae5a4SJacob Faibussowitsch { 922552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9236858538eSMatthew G. Knepley DM cdm, cdmCell; 9246858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9256858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 926552f7358SJed Brown PetscViewerFormat format; 927552f7358SJed Brown 928552f7358SJed Brown PetscFunctionBegin; 9299566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 930552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 931552f7358SJed Brown const char *name; 932f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9339318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 934552f7358SJed Brown PetscMPIInt rank, size; 935552f7358SJed Brown 9369f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9379f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9389f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9399f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9409f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9419f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9459566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9489566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 95063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 95163a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 95263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 95463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 955552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 956552f7358SJed Brown PetscInt dof, off, s; 957552f7358SJed Brown 9589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 96048a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 961552f7358SJed Brown } 9629566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 96363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 96463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 965552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 966552f7358SJed Brown PetscInt dof, off, c; 967552f7358SJed Brown 9689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 97048a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 971552f7358SJed Brown } 9729566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9743d2e540fSStefano Zampini if (coordSection && coordinates) { 97519ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9766858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 9776858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 97819ad8254SMatthew G. Knepley PetscMPIInt rank; 97919ad8254SMatthew G. Knepley const char *name; 98019ad8254SMatthew G. Knepley 9819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 9829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 9839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 98463a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 9859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 9866858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 9876858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 9886858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 9896858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 9909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 99163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 99263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9939566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 99419ad8254SMatthew G. Knepley 9959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9966858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 9989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 99919ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 100019ad8254SMatthew G. Knepley PetscInt dof, off; 100119ad8254SMatthew G. Knepley 10026858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10056858538eSMatthew G. Knepley if (dof) { 100663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10079566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 100919ad8254SMatthew G. Knepley } 10106858538eSMatthew G. Knepley } 10116858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10126858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10136858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10146858538eSMatthew G. Knepley if (dof) { 10156858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10166858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10176858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10186858538eSMatthew G. Knepley } 10196858538eSMatthew G. Knepley } 10206858538eSMatthew G. Knepley } 10219566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10246858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10253d2e540fSStefano Zampini } 10269566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10279566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10289318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10299318fe57SMatthew G. Knepley DMLabel label; 10309318fe57SMatthew G. Knepley PetscBool isdepth; 10319318fe57SMatthew G. Knepley const char *name; 10329318fe57SMatthew G. Knepley 10339566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10359318fe57SMatthew G. Knepley if (isdepth) continue; 10369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10379566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10389318fe57SMatthew G. Knepley } 1039552f7358SJed Brown if (size > 1) { 1040552f7358SJed Brown PetscSF sf; 1041552f7358SJed Brown 10429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1044552f7358SJed Brown } 10454e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 10469566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1047552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10480588280cSMatthew G. Knepley const char *name, *color; 10490588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10500588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1051fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1052552f7358SJed Brown PetscReal scale = 2.0; 105378081901SStefano Zampini PetscReal tikzscale = 1.0; 1054b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10550588280cSMatthew G. Knepley double tcoords[3]; 1056552f7358SJed Brown PetscScalar *coords; 1057b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 1058552f7358SJed Brown PetscMPIInt rank, size; 10590588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1060b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1061fe1cc32dSStefano Zampini PetscBT wp = NULL; 1062fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1063552f7358SJed Brown 10649f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10659f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10669f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10679f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10689f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10699f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10729566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10730588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10740588280cSMatthew G. Knepley numColors = 10; 10750588280cSMatthew G. Knepley numLColors = 10; 10769566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 10779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 10789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 10799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1080b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1081b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1082b7f6ffafSMatthew G. Knepley n = 4; 10839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 10841dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 1085bd3611e6SMatthew G. Knepley n = 4; 10869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10871dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 10889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10890588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10910588280cSMatthew G. Knepley if (!useColors) { 10920588280cSMatthew G. Knepley numColors = 3; 10939566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10940588280cSMatthew G. Knepley } 10959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10960588280cSMatthew G. Knepley if (!useColors) { 10970588280cSMatthew G. Knepley numLColors = 4; 10989566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 10990588280cSMatthew G. Knepley } 11009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1101b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11031dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1104202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1106fe1cc32dSStefano Zampini 1107fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1112fe1cc32dSStefano Zampini if (lflg) { 1113fe1cc32dSStefano Zampini DMLabel lbl; 1114fe1cc32dSStefano Zampini 11159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1116fe1cc32dSStefano Zampini if (lbl) { 1117fe1cc32dSStefano Zampini PetscInt val, defval; 1118fe1cc32dSStefano Zampini 11199566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11209566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1121fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1122fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1123fe1cc32dSStefano Zampini PetscInt closureSize; 1124fe1cc32dSStefano Zampini 11259566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1126fe1cc32dSStefano Zampini if (val == defval) continue; 1127fe1cc32dSStefano Zampini 11289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 112948a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1131fe1cc32dSStefano Zampini } 1132fe1cc32dSStefano Zampini } 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini 11359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11390588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1140552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1141552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1142552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11435f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11440588280cSMatthew G. Knepley if (size > 1) { 11459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1146770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114763a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 114863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1149770b213bSMatthew G Knepley } 11509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11510588280cSMatthew G. Knepley } 1152b7f6ffafSMatthew G. Knepley if (drawHasse) { 1153b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1154b7f6ffafSMatthew G. Knepley 115563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 115963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1167b7f6ffafSMatthew G. Knepley } 11689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1169fe1cc32dSStefano Zampini 1170552f7358SJed Brown /* Plot vertices */ 11719566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1173552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1174552f7358SJed Brown PetscInt off, dof, d; 11750588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1176552f7358SJed Brown 1177fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118163a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11820588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11830588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1184c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11850588280cSMatthew G. Knepley } 11860588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11879371c9d4SSatish Balay if (dim == 3) { 11889371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11899371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11909371c9d4SSatish Balay tcoords[2] = -tmp; 11919371c9d4SSatish Balay } 1192552f7358SJed Brown for (d = 0; d < dof; ++d) { 11939566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1195552f7358SJed Brown } 1196b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1197b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 11980588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 11990588280cSMatthew G. Knepley PetscInt val; 12009566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12019371c9d4SSatish Balay if (val >= 0) { 12029371c9d4SSatish Balay color = lcolors[l % numLColors]; 12039371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12049371c9d4SSatish Balay break; 12059371c9d4SSatish Balay } 12060588280cSMatthew G. Knepley } 1207b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 120863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1209b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12111baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1212552f7358SJed Brown } 12139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1215b7f6ffafSMatthew G. Knepley /* Plot edges */ 1216b7f6ffafSMatthew G. Knepley if (plotEdges) { 12179566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1219b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1220b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1221b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1222b7f6ffafSMatthew G. Knepley 1223b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122563a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1231b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1232b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1233b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1234b7f6ffafSMatthew G. Knepley } 1235b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12369371c9d4SSatish Balay if (dim == 3) { 12379371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12389371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12399371c9d4SSatish Balay tcoords[2] = -tmp; 12409371c9d4SSatish Balay } 1241b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12429566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1244b7f6ffafSMatthew G. Knepley } 1245b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1246b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1247b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1248b7f6ffafSMatthew G. Knepley PetscInt val; 1249bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12509371c9d4SSatish Balay if (val >= 0) { 12519371c9d4SSatish Balay color = lcolors[l % numLColors]; 12529371c9d4SSatish Balay break; 12539371c9d4SSatish Balay } 1254b7f6ffafSMatthew G. Knepley } 125563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1256b7f6ffafSMatthew G. Knepley } 12579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12589566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1260b7f6ffafSMatthew G. Knepley } 1261846a3e8bSMatthew G. Knepley /* Plot cells */ 1262b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1263846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1264846a3e8bSMatthew G. Knepley const PetscInt *cone; 1265846a3e8bSMatthew G. Knepley 1266fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1267846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1268846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1269846a3e8bSMatthew G. Knepley PetscInt val; 12709566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12719371c9d4SSatish Balay if (val >= 0) { 12729371c9d4SSatish Balay color = lcolors[l % numLColors]; 12739371c9d4SSatish Balay break; 12749371c9d4SSatish Balay } 1275846a3e8bSMatthew G. Knepley } 12769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1278846a3e8bSMatthew G. Knepley } 1279846a3e8bSMatthew G. Knepley } else { 1280b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1281846a3e8bSMatthew G. Knepley 1282b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1283b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1284fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1286c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1287b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1288b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1289b7f6ffafSMatthew G. Knepley 12909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1292b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1293b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1294b7f6ffafSMatthew G. Knepley 12959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1297b7f6ffafSMatthew G. Knepley } 1298b7f6ffafSMatthew G. Knepley } else { 1299b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1300b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1301b7f6ffafSMatthew G. Knepley 13029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1303846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1304846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1305846a3e8bSMatthew G. Knepley 1306b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1307846a3e8bSMatthew G. Knepley } 13089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1309b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1310b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1311b7f6ffafSMatthew G. Knepley 1312b7f6ffafSMatthew G. Knepley if (v > 0) { 1313b7f6ffafSMatthew G. Knepley if (plotEdges) { 1314b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1315b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1316b7f6ffafSMatthew G. Knepley 13179371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13189371c9d4SSatish Balay endpoints[1] = vertex; 13199566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132063a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13231baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1324b7f6ffafSMatthew G. Knepley } 132563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1326b7f6ffafSMatthew G. Knepley } 13279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1329846a3e8bSMatthew G. Knepley } 1330846a3e8bSMatthew G. Knepley } 1331b7f6ffafSMatthew G. Knepley } 1332846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1333846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1334846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1335c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1336c713ec31SMatthew G. Knepley const PetscScalar *array; 1337c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1338c713ec31SMatthew G. Knepley PetscBool isDG; 1339846a3e8bSMatthew G. Knepley 1340fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1341c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1342c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1343c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1345c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1346c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1347c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1348846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1349846a3e8bSMatthew G. Knepley } 1350846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13519371c9d4SSatish Balay if (cdim == 3) { 13529371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13539371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13549371c9d4SSatish Balay tcoords[2] = -tmp; 13559371c9d4SSatish Balay } 1356ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1357846a3e8bSMatthew G. Knepley } 1358ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1359c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1360c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13619566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1363846a3e8bSMatthew G. Knepley } 1364b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1365b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1366846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1367846a3e8bSMatthew G. Knepley PetscInt val; 13689566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13699371c9d4SSatish Balay if (val >= 0) { 13709371c9d4SSatish Balay color = lcolors[l % numLColors]; 13719371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13729371c9d4SSatish Balay break; 13739371c9d4SSatish Balay } 1374846a3e8bSMatthew G. Knepley } 1375b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1377b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 137863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13791baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1380846a3e8bSMatthew G. Knepley } 1381b7f6ffafSMatthew G. Knepley if (drawHasse) { 1382b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1388552f7358SJed Brown 1389b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1395b7f6ffafSMatthew G. Knepley 1396b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 13989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1402b7f6ffafSMatthew G. Knepley 1403b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1404b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1405b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1406b7f6ffafSMatthew G. Knepley 14079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 140948a46eb9SPierre Jolivet for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 14100588280cSMatthew G. Knepley } 14110588280cSMatthew G. Knepley } 14129566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14169566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14179566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14189566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14199566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14209566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14210f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14220f7d6e4aSStefano Zampini Vec cown, acown; 14230f7d6e4aSStefano Zampini VecScatter sct; 14240f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14250f7d6e4aSStefano Zampini IS gid, acis; 14260f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14270f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14280f7d6e4aSStefano Zampini PetscScalar *array, nid; 14290f7d6e4aSStefano Zampini const PetscInt *idxs; 14300f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14310f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14320f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14330f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14340f7d6e4aSStefano Zampini 14359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1437b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14390f7d6e4aSStefano Zampini #endif 14400f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14430f7d6e4aSStefano Zampini d1 = 0; 14449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14450f7d6e4aSStefano Zampini nid = d2; 14469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14490f7d6e4aSStefano Zampini } else nid = 0.0; 14500f7d6e4aSStefano Zampini 14510f7d6e4aSStefano Zampini /* Get connectivity */ 14529566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14539566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14540f7d6e4aSStefano Zampini 14550f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14600f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14610f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14620f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14630f7d6e4aSStefano Zampini } 14649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146563a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14680f7d6e4aSStefano Zampini 14690f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14719566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14729566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14739566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14740f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14769566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14809566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14820f7d6e4aSStefano Zampini 14830f7d6e4aSStefano Zampini /* compute edgeCut */ 14840f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14899566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14900f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14910f7d6e4aSStefano Zampini PetscInt totl; 14920f7d6e4aSStefano Zampini 14930f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14949566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14950f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14960f7d6e4aSStefano Zampini if (work[i] < 0) { 14970f7d6e4aSStefano Zampini ect += 1; 14980f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 14990f7d6e4aSStefano Zampini } 15000f7d6e4aSStefano Zampini } 15010f7d6e4aSStefano Zampini } 15029566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15040f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15050f7d6e4aSStefano Zampini lm[1] = -numVertices; 15061c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0])); 15080f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15090f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15100f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1513b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1514f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.)); 15150f7d6e4aSStefano Zampini #else 151663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15170f7d6e4aSStefano Zampini #endif 15189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15199566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1522552f7358SJed Brown } else { 1523412e9a14SMatthew G. Knepley const char *name; 1524d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1525412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1526d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1527ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15289318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1529412e9a14SMatthew G. Knepley MPI_Comm comm; 1530412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1531552f7358SJed Brown 15329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15369566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 153863a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 153963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154063a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15421c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15432827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1544d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15459566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15469566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1547412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1548412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1549412e9a14SMatthew G. Knepley 15509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15519566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1552412e9a14SMatthew G. Knepley ict = ct0; 15539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1554412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1555412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1556412e9a14SMatthew G. Knepley DMPolytopeType ct; 1557412e9a14SMatthew G. Knepley 15589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1559412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1560412e9a14SMatthew G. Knepley else ++Nc[1]; 1561412e9a14SMatthew G. Knepley } 1562ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15659566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1567834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1568dd400576SPatrick Sanan if (rank == 0) { 156963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157063a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157163a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1572834065abSMatthew G. Knepley } 1573cbb7f117SMark Adams } 1574ca7bf7eeSMatthew G. Knepley } else { 1575ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1576ca7bf7eeSMatthew G. Knepley 15779371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15789371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15799566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15809371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15819371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15829566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1583ca7bf7eeSMatthew G. Knepley if (d == depth) { 15849371c9d4SSatish Balay locMinMax[0] = gcNum; 15859371c9d4SSatish Balay locMinMax[1] = gcNum; 15869566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1587ca7bf7eeSMatthew G. Knepley } 158863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15909566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15919566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1592ca7bf7eeSMatthew G. Knepley } 15939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1594552f7358SJed Brown } 15959566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15969318fe57SMatthew G. Knepley { 15979318fe57SMatthew G. Knepley const PetscReal *maxCell; 15989318fe57SMatthew G. Knepley const PetscReal *L; 15996858538eSMatthew G. Knepley PetscBool localized; 16009318fe57SMatthew G. Knepley 16014fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16036858538eSMatthew G. Knepley if (L || localized) { 16046858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16066858538eSMatthew G. Knepley if (L) { 16076858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16089318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16096858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16106858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16119318fe57SMatthew G. Knepley } 16126858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16136858538eSMatthew G. Knepley } 16146858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16169318fe57SMatthew G. Knepley } 16179318fe57SMatthew G. Knepley } 16189566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16199566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1620a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1621a57dd577SMatthew G Knepley DMLabel label; 1622a57dd577SMatthew G Knepley const char *name; 1623a57dd577SMatthew G Knepley IS valueIS; 1624a57dd577SMatthew G Knepley const PetscInt *values; 1625a57dd577SMatthew G Knepley PetscInt numValues, v; 1626a57dd577SMatthew G Knepley 16279566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16289566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16299566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1634a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1635a57dd577SMatthew G Knepley PetscInt size; 1636a57dd577SMatthew G Knepley 16379566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16389566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 163963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1640a57dd577SMatthew G Knepley } 16419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1645a57dd577SMatthew G Knepley } 1646c1cad2e7SMatthew G. Knepley { 1647c1cad2e7SMatthew G. Knepley char **labelNames; 1648c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1649c1cad2e7SMatthew G. Knepley PetscBool flg; 1650c1cad2e7SMatthew G. Knepley 16519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1653c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1654c1cad2e7SMatthew G. Knepley DMLabel label; 1655c1cad2e7SMatthew G. Knepley 16569566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1657c1cad2e7SMatthew G. Knepley if (flg) { 16589566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16599566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1660c1cad2e7SMatthew G. Knepley } 16619566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1662c1cad2e7SMatthew G. Knepley } 16639566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1664c1cad2e7SMatthew G. Knepley } 166534aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166634aa8a36SMatthew G. Knepley if (dm->Nf) { 166734aa8a36SMatthew G. Knepley PetscInt f; 166834aa8a36SMatthew G. Knepley 166934aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167034aa8a36SMatthew G. Knepley const char *name; 167134aa8a36SMatthew G. Knepley 16729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16739566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16759566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167634aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16779566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16789566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 167934aa8a36SMatthew G. Knepley } else { 16809566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16819566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168234aa8a36SMatthew G. Knepley } 16839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168434aa8a36SMatthew G. Knepley } 168534aa8a36SMatthew G. Knepley } 16869566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16878e7ff633SMatthew G. Knepley if (cdm) { 16889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16899f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16909566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16928e7ff633SMatthew G. Knepley } 1693552f7358SJed Brown } 16943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1695552f7358SJed Brown } 1696552f7358SJed Brown 1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1698d71ae5a4SJacob Faibussowitsch { 1699e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1700e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1701a12d352dSMatthew G. Knepley PetscInt cdim; 1702e5c487bfSMatthew G. Knepley 1703e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1707e5c487bfSMatthew G. Knepley switch (ct) { 1708a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1709a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1710a12d352dSMatthew G. Knepley switch (cdim) { 17119371c9d4SSatish Balay case 1: { 1712a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1713a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1714a12d352dSMatthew G. Knepley 17159566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17169566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17189371c9d4SSatish Balay } break; 17199371c9d4SSatish Balay case 2: { 1720a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1721a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1722a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1723a12d352dSMatthew G. Knepley 17249566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17259566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK)); 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK)); 17279371c9d4SSatish Balay } break; 1728d71ae5a4SJacob Faibussowitsch default: 1729d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1730a12d352dSMatthew G. Knepley } 1731a12d352dSMatthew G. Knepley break; 1732e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17339371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17349566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17359566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1737e5c487bfSMatthew G. Knepley break; 1738e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17399371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17409371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17419566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1745e5c487bfSMatthew G. Knepley break; 17469f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17479f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17489f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17499f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17509f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley break; 1754d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1755d71ae5a4SJacob Faibussowitsch break; 1756d71ae5a4SJacob Faibussowitsch default: 1757d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1758e5c487bfSMatthew G. Knepley } 17593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1760e5c487bfSMatthew G. Knepley } 1761e5c487bfSMatthew G. Knepley 1762c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1763d71ae5a4SJacob Faibussowitsch { 1764e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1765e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1766c5aedaa3SMatthew G. Knepley PetscInt fillColor; 1767e5c487bfSMatthew G. Knepley 1768e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1770e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1771c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1772c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1773c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 17749371c9d4SSatish Balay } 1775c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1776e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1777e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1778c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1779c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1780c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1781e5c487bfSMatthew G. Knepley } 17829566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1783c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 17849566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor)); 17859566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK)); 1786e5c487bfSMatthew G. Knepley } 1787e5c487bfSMatthew G. Knepley } 1788c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1789c5aedaa3SMatthew G. Knepley } 1790c5aedaa3SMatthew G. Knepley 1791c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1792c5aedaa3SMatthew G. Knepley { 1793c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1794c5aedaa3SMatthew G. Knepley 1795c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1796c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1797c5aedaa3SMatthew G. Knepley switch (ct) { 1798c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1799c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1800c5aedaa3SMatthew G. Knepley 1801c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1802c5aedaa3SMatthew G. Knepley } break; 1803c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1804c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1805c5aedaa3SMatthew G. Knepley 1806c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 18079371c9d4SSatish Balay } break; 1808d71ae5a4SJacob Faibussowitsch default: 1809d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1810e5c487bfSMatthew G. Knepley } 18113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1812e5c487bfSMatthew G. Knepley } 1813e5c487bfSMatthew G. Knepley 1814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1815d71ae5a4SJacob Faibussowitsch { 1816e412dcbdSMatthew G. Knepley PetscDraw draw; 1817e412dcbdSMatthew G. Knepley DM cdm; 1818e412dcbdSMatthew G. Knepley PetscSection coordSection; 1819e412dcbdSMatthew G. Knepley Vec coordinates; 1820c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1821e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1822c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1823c5aedaa3SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv; 1824e412dcbdSMatthew G. Knepley 1825e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 182763a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1828c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1829c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1830c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 18319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18329566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18349566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18379566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1838e412dcbdSMatthew G. Knepley 18399566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18409566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18413ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18429566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1843e412dcbdSMatthew G. Knepley 1844c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18459566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18469566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1847e412dcbdSMatthew G. Knepley 1848cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1849cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1850c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1851ba2698f1SMatthew G. Knepley PetscInt numCoords; 1852c9c77995SMatthew G. Knepley PetscBool isDG; 1853cf3064d3SMatthew G. Knepley 1854c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18551baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18561baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1857c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1858cf3064d3SMatthew G. Knepley } 18599566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18609566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18619566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18629566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1864e412dcbdSMatthew G. Knepley } 1865e412dcbdSMatthew G. Knepley 1866e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1867e44f6aebSMatthew G. Knepley { 1868e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1869e44f6aebSMatthew G. Knepley PetscFE fe; 1870e44f6aebSMatthew G. Knepley PetscSpace sp; 1871e44f6aebSMatthew G. Knepley PetscClassId id; 1872e44f6aebSMatthew G. Knepley PetscInt degree; 1873e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1874e44f6aebSMatthew G. Knepley 1875e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1876e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1877e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1878e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1879e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1880e44f6aebSMatthew G. Knepley *hdm = dm; 1881e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1882e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1883e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1884e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1885e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1886e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1887e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1888e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1889e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1890e44f6aebSMatthew G. Knepley Mat In; 1891e44f6aebSMatthew G. Knepley Vec cl, rcl; 1892e44f6aebSMatthew G. Knepley 1893e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1894c5aedaa3SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1895e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1896e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1897e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1898e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1899e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1900e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1901e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1902e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1903e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1904e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1905e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1906e44f6aebSMatthew G. Knepley odm = rdm; 1907e44f6aebSMatthew G. Knepley } 1908e44f6aebSMatthew G. Knepley *hdm = rdm; 1909e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1910e44f6aebSMatthew G. Knepley } 1911e44f6aebSMatthew G. Knepley 19121e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19131e50132fSMatthew G. Knepley #include <exodusII.h> 19146823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19151e50132fSMatthew G. Knepley #endif 19161e50132fSMatthew G. Knepley 1917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1918d71ae5a4SJacob Faibussowitsch { 19195f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1920002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1921552f7358SJed Brown 1922552f7358SJed Brown PetscFunctionBegin; 1923552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1924552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19315f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1932552f7358SJed Brown if (iascii) { 19338135c375SStefano Zampini PetscViewerFormat format; 19349566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19351baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19361baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1937c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1938c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19399566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1940c6ccd67eSMatthew G. Knepley #else 1941c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1942552f7358SJed Brown #endif 1943e412dcbdSMatthew G. Knepley } else if (isvtk) { 19449566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1945e412dcbdSMatthew G. Knepley } else if (isdraw) { 1946e44f6aebSMatthew G. Knepley DM hdm; 1947e44f6aebSMatthew G. Knepley 1948e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1949e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1950e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19518135c375SStefano Zampini } else if (isglvis) { 19529566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19531e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19541e50132fSMatthew G. Knepley } else if (isexodus) { 19556823f3c5SBlaise Bourdin /* 19566823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19576823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1958da81f932SPierre Jolivet with ID 1, containing all cells. 19596823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19606823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19616823f3c5SBlaise Bourdin */ 19626823f3c5SBlaise Bourdin PetscInt numCS; 19639566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19646823f3c5SBlaise Bourdin if (!numCS) { 19651e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19669566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19689566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19696823f3c5SBlaise Bourdin } 19709566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19711e50132fSMatthew G. Knepley #endif 19725f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19735f34f2dcSJed Brown } else if (iscgns) { 19745f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19755f34f2dcSJed Brown #endif 19761baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1977cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19789566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1979cb3ba0daSMatthew G. Knepley if (flg) { 1980cb3ba0daSMatthew G. Knepley Vec ranks; 19819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19829566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1984cb3ba0daSMatthew G. Knepley } 1985002a2709SMatthew G. Knepley /* Optionally view a label */ 19869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1987002a2709SMatthew G. Knepley if (flg) { 1988002a2709SMatthew G. Knepley DMLabel label; 1989002a2709SMatthew G. Knepley Vec val; 1990002a2709SMatthew G. Knepley 19919566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 199228b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19949566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1996002a2709SMatthew G. Knepley } 19973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1998552f7358SJed Brown } 1999552f7358SJed Brown 20007f96f51bSksagiyam /*@ 2001a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 20027f96f51bSksagiyam 200320f4b53cSBarry Smith Collective 20047f96f51bSksagiyam 20057f96f51bSksagiyam Input Parameters: 2006a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2007a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 20087f96f51bSksagiyam 20097f96f51bSksagiyam Level: advanced 20107f96f51bSksagiyam 20111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 20127f96f51bSksagiyam @*/ 2013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2014d71ae5a4SJacob Faibussowitsch { 20157f96f51bSksagiyam PetscBool ishdf5; 20167f96f51bSksagiyam 20177f96f51bSksagiyam PetscFunctionBegin; 20187f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20197f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20227f96f51bSksagiyam if (ishdf5) { 20237f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20247f96f51bSksagiyam PetscViewerFormat format; 20259566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20267f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20277f96f51bSksagiyam IS globalPointNumbering; 20287f96f51bSksagiyam 20299566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20309566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 203298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20337f96f51bSksagiyam #else 20347f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20357f96f51bSksagiyam #endif 20367f96f51bSksagiyam } 20379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20397f96f51bSksagiyam } 20407f96f51bSksagiyam 204177b8e257Sksagiyam /*@ 2042a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 204377b8e257Sksagiyam 204420f4b53cSBarry Smith Collective 204577b8e257Sksagiyam 204677b8e257Sksagiyam Input Parameters: 2047a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2048a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 204977b8e257Sksagiyam 205077b8e257Sksagiyam Level: advanced 205177b8e257Sksagiyam 20521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 205377b8e257Sksagiyam @*/ 2054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2055d71ae5a4SJacob Faibussowitsch { 205677b8e257Sksagiyam PetscBool ishdf5; 205777b8e257Sksagiyam 205877b8e257Sksagiyam PetscFunctionBegin; 205977b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 206077b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 206377b8e257Sksagiyam if (ishdf5) { 206477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 206577b8e257Sksagiyam PetscViewerFormat format; 20669566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 206777b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20689566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2069fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 207077b8e257Sksagiyam #else 207177b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 207277b8e257Sksagiyam #endif 207377b8e257Sksagiyam } 20749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207677b8e257Sksagiyam } 207777b8e257Sksagiyam 2078bd6565f1Sksagiyam /*@ 2079a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2080bd6565f1Sksagiyam 208120f4b53cSBarry Smith Collective 2082bd6565f1Sksagiyam 2083bd6565f1Sksagiyam Input Parameters: 2084a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2085a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2086bd6565f1Sksagiyam 2087bd6565f1Sksagiyam Level: advanced 2088bd6565f1Sksagiyam 20891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2090bd6565f1Sksagiyam @*/ 2091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2092d71ae5a4SJacob Faibussowitsch { 2093bd6565f1Sksagiyam PetscBool ishdf5; 2094bd6565f1Sksagiyam 2095bd6565f1Sksagiyam PetscFunctionBegin; 2096bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2097bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2100bd6565f1Sksagiyam if (ishdf5) { 2101bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2102bd6565f1Sksagiyam IS globalPointNumbering; 2103bd6565f1Sksagiyam PetscViewerFormat format; 2104bd6565f1Sksagiyam 21059566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2106bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21079566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21089566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 211098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2111bd6565f1Sksagiyam #else 2112bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2113bd6565f1Sksagiyam #endif 2114bd6565f1Sksagiyam } 21159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2117bd6565f1Sksagiyam } 2118bd6565f1Sksagiyam 2119021affd3Sksagiyam /*@ 2120a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2121021affd3Sksagiyam 212220f4b53cSBarry Smith Collective 2123021affd3Sksagiyam 2124021affd3Sksagiyam Input Parameters: 2125a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2126a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 21270318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2128021affd3Sksagiyam 2129021affd3Sksagiyam Level: advanced 2130021affd3Sksagiyam 2131021affd3Sksagiyam Notes: 2132420bcc1bSBarry Smith This function is a wrapper around `PetscSectionView()`; in addition to the raw section, it saves information that associates the section points to the topology (`dm`) points. When the topology (`dm`) and the section are later loaded with `DMPlexTopologyLoad()` and `DMPlexSectionLoad()`, respectively, this information is used to match section points with topology points. 2133021affd3Sksagiyam 21340318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2135021affd3Sksagiyam 21361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2137021affd3Sksagiyam @*/ 2138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2139d71ae5a4SJacob Faibussowitsch { 2140021affd3Sksagiyam PetscBool ishdf5; 2141021affd3Sksagiyam 2142021affd3Sksagiyam PetscFunctionBegin; 2143021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2144021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21450318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2146021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2149021affd3Sksagiyam if (ishdf5) { 2150021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21519566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2152021affd3Sksagiyam #else 2153021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2154021affd3Sksagiyam #endif 2155021affd3Sksagiyam } 21569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2158021affd3Sksagiyam } 2159021affd3Sksagiyam 21603e97647fSksagiyam /*@ 21613e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21623e97647fSksagiyam 216320f4b53cSBarry Smith Collective 21643e97647fSksagiyam 21653e97647fSksagiyam Input Parameters: 2166a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2167a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 21680318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 21693e97647fSksagiyam - vec - The global vector to be saved 21703e97647fSksagiyam 21713e97647fSksagiyam Level: advanced 21723e97647fSksagiyam 21733e97647fSksagiyam Notes: 21740318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 21753e97647fSksagiyam 217660225df5SJacob Faibussowitsch Calling sequence: 2177a1cb98faSBarry Smith .vb 2178a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2179a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2180a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2181a1cb98faSBarry Smith DMClone(dm, §iondm); 2182a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2183a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2184a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2185a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2186a1cb98faSBarry Smith PetscSectionSetUp(section); 2187a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2188a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2189a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2190a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2191a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2192a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2193a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2194a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2195a1cb98faSBarry Smith DMDestroy(§iondm); 2196a1cb98faSBarry Smith DMDestroy(&dm); 2197a1cb98faSBarry Smith .ve 21983e97647fSksagiyam 21991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22003e97647fSksagiyam @*/ 2201d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2202d71ae5a4SJacob Faibussowitsch { 22033e97647fSksagiyam PetscBool ishdf5; 22043e97647fSksagiyam 22053e97647fSksagiyam PetscFunctionBegin; 22063e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22073e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22080318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22093e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22103e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22113e97647fSksagiyam /* Check consistency */ 22123e97647fSksagiyam { 22133e97647fSksagiyam PetscSection section; 22143e97647fSksagiyam PetscBool includesConstraints; 22153e97647fSksagiyam PetscInt m, m1; 22163e97647fSksagiyam 22179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22189566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22209566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22219566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 222263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22233e97647fSksagiyam } 22249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22263e97647fSksagiyam if (ishdf5) { 22273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22289566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22293e97647fSksagiyam #else 22303e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22313e97647fSksagiyam #endif 22323e97647fSksagiyam } 22339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22353e97647fSksagiyam } 22363e97647fSksagiyam 22373e97647fSksagiyam /*@ 22383e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22393e97647fSksagiyam 224020f4b53cSBarry Smith Collective 22413e97647fSksagiyam 22423e97647fSksagiyam Input Parameters: 2243a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2244a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 22463e97647fSksagiyam - vec - The local vector to be saved 22473e97647fSksagiyam 22483e97647fSksagiyam Level: advanced 22493e97647fSksagiyam 2250a1cb98faSBarry Smith Note: 22510318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 22523e97647fSksagiyam 225360225df5SJacob Faibussowitsch Calling sequence: 2254a1cb98faSBarry Smith .vb 2255a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2256a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2257a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2258a1cb98faSBarry Smith DMClone(dm, §iondm); 2259a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2260a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2261a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2262a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2263a1cb98faSBarry Smith PetscSectionSetUp(section); 2264a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2265a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2266a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2267a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2268a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2269a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2270a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2271a1cb98faSBarry Smith DMDestroy(§iondm); 2272a1cb98faSBarry Smith DMDestroy(&dm); 2273a1cb98faSBarry Smith .ve 22743e97647fSksagiyam 22751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22763e97647fSksagiyam @*/ 2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2278d71ae5a4SJacob Faibussowitsch { 22793e97647fSksagiyam PetscBool ishdf5; 22803e97647fSksagiyam 22813e97647fSksagiyam PetscFunctionBegin; 22823e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22833e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22840318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22853e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22863e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22873e97647fSksagiyam /* Check consistency */ 22883e97647fSksagiyam { 22893e97647fSksagiyam PetscSection section; 22903e97647fSksagiyam PetscBool includesConstraints; 22913e97647fSksagiyam PetscInt m, m1; 22923e97647fSksagiyam 22939566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22969566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22979566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 229863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 22993e97647fSksagiyam } 23009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23023e97647fSksagiyam if (ishdf5) { 23033e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23049566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23053e97647fSksagiyam #else 23063e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23073e97647fSksagiyam #endif 23083e97647fSksagiyam } 23099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23113e97647fSksagiyam } 23123e97647fSksagiyam 2313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2314d71ae5a4SJacob Faibussowitsch { 2315d4f5a9a0SVaclav Hapla PetscBool ishdf5; 23162c40f234SMatthew G. Knepley 23172c40f234SMatthew G. Knepley PetscFunctionBegin; 23182c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23192c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2321d4f5a9a0SVaclav Hapla if (ishdf5) { 23222c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23239c48423bSVaclav Hapla PetscViewerFormat format; 23249566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23259c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23269566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2327509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23289566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 232998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23312c40f234SMatthew G. Knepley #else 23322c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2333552f7358SJed Brown #endif 233498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2335552f7358SJed Brown } 2336552f7358SJed Brown 2337ea8e1828Sksagiyam /*@ 2338a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2339ea8e1828Sksagiyam 234020f4b53cSBarry Smith Collective 2341ea8e1828Sksagiyam 2342ea8e1828Sksagiyam Input Parameters: 2343a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2344a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2345ea8e1828Sksagiyam 23462fe279fdSBarry Smith Output Parameter: 234720f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded 2348dec9e869Sksagiyam 2349ea8e1828Sksagiyam Level: advanced 2350ea8e1828Sksagiyam 23511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2352a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2353ea8e1828Sksagiyam @*/ 2354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2355d71ae5a4SJacob Faibussowitsch { 2356ea8e1828Sksagiyam PetscBool ishdf5; 2357ea8e1828Sksagiyam 2358ea8e1828Sksagiyam PetscFunctionBegin; 2359ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2360ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23614f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2364ea8e1828Sksagiyam if (ishdf5) { 2365ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2366ea8e1828Sksagiyam PetscViewerFormat format; 23679566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2368ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23699566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 237098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2371ea8e1828Sksagiyam #else 2372ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2373ea8e1828Sksagiyam #endif 2374ea8e1828Sksagiyam } 23759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2377ea8e1828Sksagiyam } 2378ea8e1828Sksagiyam 23793e701f1cSksagiyam /*@ 2380a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23813e701f1cSksagiyam 238220f4b53cSBarry Smith Collective 23833e701f1cSksagiyam 23843e701f1cSksagiyam Input Parameters: 2385a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2386a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2387a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23883e701f1cSksagiyam 23893e701f1cSksagiyam Level: advanced 23903e701f1cSksagiyam 23911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2392a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23933e701f1cSksagiyam @*/ 2394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2395d71ae5a4SJacob Faibussowitsch { 23963e701f1cSksagiyam PetscBool ishdf5; 23973e701f1cSksagiyam 23983e701f1cSksagiyam PetscFunctionBegin; 23993e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24003e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2401c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24043e701f1cSksagiyam if (ishdf5) { 24053e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 24063e701f1cSksagiyam PetscViewerFormat format; 24079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24083e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24099566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 241098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24113e701f1cSksagiyam #else 24123e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24133e701f1cSksagiyam #endif 24143e701f1cSksagiyam } 24159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24173e701f1cSksagiyam } 24183e701f1cSksagiyam 2419b08ad5deSksagiyam /*@ 2420a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2421b08ad5deSksagiyam 242220f4b53cSBarry Smith Collective 2423b08ad5deSksagiyam 2424b08ad5deSksagiyam Input Parameters: 2425a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2426a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 242720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2428b08ad5deSksagiyam 2429b08ad5deSksagiyam Level: advanced 2430b08ad5deSksagiyam 2431a1cb98faSBarry Smith Note: 2432a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2433e6368b79SVaclav Hapla 24341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2435a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2436b08ad5deSksagiyam @*/ 2437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2438d71ae5a4SJacob Faibussowitsch { 2439b08ad5deSksagiyam PetscBool ishdf5; 2440b08ad5deSksagiyam 2441b08ad5deSksagiyam PetscFunctionBegin; 2442b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2443b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2444e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2447b08ad5deSksagiyam if (ishdf5) { 2448b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2449b08ad5deSksagiyam PetscViewerFormat format; 2450b08ad5deSksagiyam 24519566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2452b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24539566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 245498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2455b08ad5deSksagiyam #else 2456b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2457b08ad5deSksagiyam #endif 2458b08ad5deSksagiyam } 24599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2461b08ad5deSksagiyam } 2462b08ad5deSksagiyam 2463f84dd6b4Sksagiyam /*@ 2464a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2465f84dd6b4Sksagiyam 246620f4b53cSBarry Smith Collective 2467f84dd6b4Sksagiyam 2468f84dd6b4Sksagiyam Input Parameters: 2469a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2470a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 24710318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2472a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2473f84dd6b4Sksagiyam 2474a4e35b19SJacob Faibussowitsch Output Parameters: 247520f4b53cSBarry Smith + globalDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a global `Vec` associated with the `sectiondm`'s global section (`NULL` if not needed) 247620f4b53cSBarry Smith - localDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a local `Vec` associated with the `sectiondm`'s local section (`NULL` if not needed) 2477f84dd6b4Sksagiyam 2478f84dd6b4Sksagiyam Level: advanced 2479f84dd6b4Sksagiyam 2480f84dd6b4Sksagiyam Notes: 248120f4b53cSBarry Smith This function is a wrapper around `PetscSectionLoad()`; it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in `dm`. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points. 2482f84dd6b4Sksagiyam 24830318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2484f84dd6b4Sksagiyam 248520f4b53cSBarry Smith The output parameter, `globalDofSF` (`localDofSF`), can later be used with `DMPlexGlobalVectorLoad()` (`DMPlexLocalVectorLoad()`) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section. 2486f84dd6b4Sksagiyam 2487f84dd6b4Sksagiyam Example using 2 processes: 2488a1cb98faSBarry Smith .vb 2489a1cb98faSBarry Smith NX (number of points on dm): 4 2490a1cb98faSBarry Smith sectionA : the on-disk section 2491a1cb98faSBarry Smith vecA : a vector associated with sectionA 2492a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2493a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2494a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2495f84dd6b4Sksagiyam 2496a1cb98faSBarry Smith rank 0 rank 1 2497a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2498a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2499a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2500a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2501a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2502a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2503a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2504a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2505a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2506a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2507a1cb98faSBarry Smith .ve 2508a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2509a1cb98faSBarry Smith 25101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2511f84dd6b4Sksagiyam @*/ 2512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2513d71ae5a4SJacob Faibussowitsch { 2514f84dd6b4Sksagiyam PetscBool ishdf5; 2515f84dd6b4Sksagiyam 2516f84dd6b4Sksagiyam PetscFunctionBegin; 2517f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2518f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25190318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2520f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2521f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25224f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25234f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2526f84dd6b4Sksagiyam if (ishdf5) { 2527f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25289566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2529f84dd6b4Sksagiyam #else 2530f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2531f84dd6b4Sksagiyam #endif 2532f84dd6b4Sksagiyam } 25339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2535f84dd6b4Sksagiyam } 2536f84dd6b4Sksagiyam 25378be3dfe1Sksagiyam /*@ 25388be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25398be3dfe1Sksagiyam 254020f4b53cSBarry Smith Collective 25418be3dfe1Sksagiyam 25428be3dfe1Sksagiyam Input Parameters: 2543a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2544a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 25450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2546a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25478be3dfe1Sksagiyam - vec - The global vector to set values of 25488be3dfe1Sksagiyam 25498be3dfe1Sksagiyam Level: advanced 25508be3dfe1Sksagiyam 25518be3dfe1Sksagiyam Notes: 25520318f8a0SStefano Zampini In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 25538be3dfe1Sksagiyam 255460225df5SJacob Faibussowitsch Calling sequence: 2555a1cb98faSBarry Smith .vb 2556a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2557a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2558a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2559a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2560a1cb98faSBarry Smith DMClone(dm, §iondm); 2561a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2562a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2563a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2564a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2565a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2566a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2567a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2568a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2569a1cb98faSBarry Smith DMDestroy(§iondm); 2570a1cb98faSBarry Smith DMDestroy(&dm); 2571a1cb98faSBarry Smith .ve 25728be3dfe1Sksagiyam 25731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2574a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25758be3dfe1Sksagiyam @*/ 2576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2577d71ae5a4SJacob Faibussowitsch { 25788be3dfe1Sksagiyam PetscBool ishdf5; 25798be3dfe1Sksagiyam 25808be3dfe1Sksagiyam PetscFunctionBegin; 25818be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25828be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25830318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 25848be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25858be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25868be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25878be3dfe1Sksagiyam /* Check consistency */ 25888be3dfe1Sksagiyam { 25898be3dfe1Sksagiyam PetscSection section; 25908be3dfe1Sksagiyam PetscBool includesConstraints; 25918be3dfe1Sksagiyam PetscInt m, m1; 25928be3dfe1Sksagiyam 25939566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25949566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25969566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25979566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 259863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 25998be3dfe1Sksagiyam } 26009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26028be3dfe1Sksagiyam if (ishdf5) { 26038be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26049566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26058be3dfe1Sksagiyam #else 26068be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26078be3dfe1Sksagiyam #endif 26088be3dfe1Sksagiyam } 26099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26118be3dfe1Sksagiyam } 26128be3dfe1Sksagiyam 26138be3dfe1Sksagiyam /*@ 26148be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 26158be3dfe1Sksagiyam 261620f4b53cSBarry Smith Collective 26178be3dfe1Sksagiyam 26188be3dfe1Sksagiyam Input Parameters: 2619a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2620a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26210318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2622a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26238be3dfe1Sksagiyam - vec - The local vector to set values of 26248be3dfe1Sksagiyam 26258be3dfe1Sksagiyam Level: advanced 26268be3dfe1Sksagiyam 26278be3dfe1Sksagiyam Notes: 26280318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 26298be3dfe1Sksagiyam 263060225df5SJacob Faibussowitsch Calling sequence: 2631a1cb98faSBarry Smith .vb 2632a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2633a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2634a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2635a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2636a1cb98faSBarry Smith DMClone(dm, §iondm); 2637a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2638a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2639a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2640a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2641a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2642a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2643a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2644a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2645a1cb98faSBarry Smith DMDestroy(§iondm); 2646a1cb98faSBarry Smith DMDestroy(&dm); 2647a1cb98faSBarry Smith .ve 26488be3dfe1Sksagiyam 26491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2650a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26518be3dfe1Sksagiyam @*/ 2652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2653d71ae5a4SJacob Faibussowitsch { 26548be3dfe1Sksagiyam PetscBool ishdf5; 26558be3dfe1Sksagiyam 26568be3dfe1Sksagiyam PetscFunctionBegin; 26578be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26588be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26590318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 26608be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26618be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26628be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26638be3dfe1Sksagiyam /* Check consistency */ 26648be3dfe1Sksagiyam { 26658be3dfe1Sksagiyam PetscSection section; 26668be3dfe1Sksagiyam PetscBool includesConstraints; 26678be3dfe1Sksagiyam PetscInt m, m1; 26688be3dfe1Sksagiyam 26699566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26729566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26739566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 267463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26758be3dfe1Sksagiyam } 26769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26788be3dfe1Sksagiyam if (ishdf5) { 26798be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26809566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26818be3dfe1Sksagiyam #else 26828be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26838be3dfe1Sksagiyam #endif 26848be3dfe1Sksagiyam } 26859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26878be3dfe1Sksagiyam } 26888be3dfe1Sksagiyam 2689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2690d71ae5a4SJacob Faibussowitsch { 2691552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2692552f7358SJed Brown 2693552f7358SJed Brown PetscFunctionBegin; 26949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26986c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 26992e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 27002e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 27012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 27022e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 27036bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 27046bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2705adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2706adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2707adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2708adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2709c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2710c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2711d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2712d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 27135f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 27143ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 27159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 27189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 27199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 27209566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 272121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27229f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 27239566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27249566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27259566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27261d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27289566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27324e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27336725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27346725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27389566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27399566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27419566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27429566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27439566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27449566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27459566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2746552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27479566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2749552f7358SJed Brown } 2750552f7358SJed Brown 2751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2752d71ae5a4SJacob Faibussowitsch { 2753d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2754acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27559fca9976SJed Brown PetscInt localSize, localStart = 0; 2756837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2757b412c318SBarry Smith MatType mtype; 27581428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2759552f7358SJed Brown 2760552f7358SJed Brown PetscFunctionBegin; 27619566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2762b412c318SBarry Smith mtype = dm->mattype; 2763d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 27649566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27659566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27679fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27689566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27709566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27719566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27729566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2773acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27769566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27799566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2782552f7358SJed Brown if (!isShell) { 2783837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27849fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2785863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2786552f7358SJed Brown 27879566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27889fca9976SJed Brown 27899fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2791863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2792e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2793863027abSJed Brown switch (dm->blocking_type) { 27940e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27959fca9976SJed Brown PetscInt bdof, offset; 2796a9d99c84SMatthew G. Knepley 27979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27989fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 27999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 2800d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2801d02c7345SMatthew G. Knepley // Signal block concatenation 2802d02c7345SMatthew G. Knepley if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof); 28031d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 28041d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 28051d17a0a3SMatthew G. Knepley if (dof) { 28069371c9d4SSatish Balay if (bs < 0) { 28079371c9d4SSatish Balay bs = bdof; 28089371c9d4SSatish Balay } else if (bs != bdof) { 28099371c9d4SSatish Balay bs = 1; 28109371c9d4SSatish Balay } 2811552f7358SJed Brown } 2812863027abSJed Brown } break; 2813863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2814863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2815863027abSJed Brown PetscInt num_comp, bdof, offset; 2816863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2817863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2818863027abSJed Brown if (dof < 0) continue; 2819863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2820863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2821863027abSJed Brown PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp); 2822863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2823863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2824863027abSJed Brown // Handle possibly constant block size (unlikely) 2825863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2826863027abSJed Brown if (dof) { 2827863027abSJed Brown if (bs < 0) { 2828863027abSJed Brown bs = bdof; 2829863027abSJed Brown } else if (bs != bdof) { 2830863027abSJed Brown bs = 1; 2831863027abSJed Brown } 2832863027abSJed Brown } 2833863027abSJed Brown } 2834863027abSJed Brown } break; 2835863027abSJed Brown } 28362a28c762SMatthew G Knepley } 28372a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2838e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2839e432b41dSStefano Zampini bsLocal[1] = bs; 28409566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2841e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2842e432b41dSStefano Zampini else bs = bsMinMax[0]; 28436fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28449566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28450682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28469566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28479566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28480682b8bbSJed Brown } else { 28499566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28509566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28519566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2852552f7358SJed Brown } 28539fca9976SJed Brown { // Consolidate blocks 28549fca9976SJed Brown PetscInt nblocks = 0; 28559fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28569fca9976SJed Brown if (pblocks[i] == 0) continue; 2857d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2858d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2859d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2860d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2861d02c7345SMatthew G. Knepley } else { 28629fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2863d02c7345SMatthew G. Knepley } 2864ad540459SPierre Jolivet for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]); 28659fca9976SJed Brown } 28669fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28679fca9976SJed Brown } 28689fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2869aa0f6e3cSJed Brown } 28709566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2872552f7358SJed Brown } 2873552f7358SJed Brown 28747cd05799SMatthew G. Knepley /*@ 2875a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2876be36d101SStefano Zampini 2877a1cb98faSBarry Smith Not Collective 2878be36d101SStefano Zampini 2879be36d101SStefano Zampini Input Parameter: 288060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2881be36d101SStefano Zampini 28822fe279fdSBarry Smith Output Parameter: 2883be36d101SStefano Zampini . subsection - The subdomain section 2884be36d101SStefano Zampini 2885be36d101SStefano Zampini Level: developer 2886be36d101SStefano Zampini 28871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28887cd05799SMatthew G. Knepley @*/ 2889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2890d71ae5a4SJacob Faibussowitsch { 2891be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2892be36d101SStefano Zampini 2893be36d101SStefano Zampini PetscFunctionBegin; 2894be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2895be36d101SStefano Zampini if (!mesh->subdomainSection) { 2896be36d101SStefano Zampini PetscSection section; 2897be36d101SStefano Zampini PetscSF sf; 2898be36d101SStefano Zampini 28999566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 29009566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2901eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 29029566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2903be36d101SStefano Zampini } 2904be36d101SStefano Zampini *subsection = mesh->subdomainSection; 29053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2906be36d101SStefano Zampini } 2907be36d101SStefano Zampini 2908552f7358SJed Brown /*@ 290920f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2910552f7358SJed Brown 2911a1cb98faSBarry Smith Not Collective 2912552f7358SJed Brown 2913552f7358SJed Brown Input Parameter: 291460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2915552f7358SJed Brown 2916552f7358SJed Brown Output Parameters: 2917552f7358SJed Brown + pStart - The first mesh point 2918552f7358SJed Brown - pEnd - The upper bound for mesh points 2919552f7358SJed Brown 2920552f7358SJed Brown Level: beginner 2921552f7358SJed Brown 29221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2923552f7358SJed Brown @*/ 2924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2925d71ae5a4SJacob Faibussowitsch { 2926552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2927552f7358SJed Brown 2928552f7358SJed Brown PetscFunctionBegin; 2929552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29309f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 29319f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 29323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2933552f7358SJed Brown } 2934552f7358SJed Brown 2935552f7358SJed Brown /*@ 293620f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2937552f7358SJed Brown 2938a1cb98faSBarry Smith Not Collective 2939552f7358SJed Brown 2940552f7358SJed Brown Input Parameters: 294160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2942552f7358SJed Brown . pStart - The first mesh point 2943552f7358SJed Brown - pEnd - The upper bound for mesh points 2944552f7358SJed Brown 2945552f7358SJed Brown Level: beginner 2946552f7358SJed Brown 29471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2948552f7358SJed Brown @*/ 2949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2950d71ae5a4SJacob Faibussowitsch { 2951552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2952552f7358SJed Brown 2953552f7358SJed Brown PetscFunctionBegin; 2954552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 295721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2959552f7358SJed Brown } 2960552f7358SJed Brown 2961552f7358SJed Brown /*@ 2962eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2963552f7358SJed Brown 2964a1cb98faSBarry Smith Not Collective 2965552f7358SJed Brown 2966552f7358SJed Brown Input Parameters: 296760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2968a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2969552f7358SJed Brown 2970552f7358SJed Brown Output Parameter: 297120f4b53cSBarry Smith . size - The cone size for point `p` 2972552f7358SJed Brown 2973552f7358SJed Brown Level: beginner 2974552f7358SJed Brown 29751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2976552f7358SJed Brown @*/ 2977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2978d71ae5a4SJacob Faibussowitsch { 2979552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2980552f7358SJed Brown 2981552f7358SJed Brown PetscFunctionBegin; 2982552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29834f572ea9SToby Isaac PetscAssertPointer(size, 3); 29849f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29859f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2987552f7358SJed Brown } 2988552f7358SJed Brown 2989552f7358SJed Brown /*@ 2990eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2991552f7358SJed Brown 2992a1cb98faSBarry Smith Not Collective 2993552f7358SJed Brown 2994552f7358SJed Brown Input Parameters: 299560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2996a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 299720f4b53cSBarry Smith - size - The cone size for point `p` 2998552f7358SJed Brown 2999552f7358SJed Brown Level: beginner 3000552f7358SJed Brown 3001a1cb98faSBarry Smith Note: 3002a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3003a1cb98faSBarry Smith 30041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3005552f7358SJed Brown @*/ 3006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3007d71ae5a4SJacob Faibussowitsch { 3008552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3009552f7358SJed Brown 3010552f7358SJed Brown PetscFunctionBegin; 3011552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30129f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3015552f7358SJed Brown } 3016552f7358SJed Brown 3017552f7358SJed Brown /*@C 3018eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3019552f7358SJed Brown 3020a1cb98faSBarry Smith Not Collective 3021552f7358SJed Brown 3022552f7358SJed Brown Input Parameters: 3023a1cb98faSBarry Smith + dm - The `DMPLEX` 3024a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3025552f7358SJed Brown 3026552f7358SJed Brown Output Parameter: 302720f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 3028552f7358SJed Brown 3029552f7358SJed Brown Level: beginner 3030552f7358SJed Brown 303160225df5SJacob Faibussowitsch Fortran Notes: 3032a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3033a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30343813dfbdSMatthew G Knepley 30351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3036552f7358SJed Brown @*/ 3037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3038d71ae5a4SJacob Faibussowitsch { 3039552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3040552f7358SJed Brown PetscInt off; 3041552f7358SJed Brown 3042552f7358SJed Brown PetscFunctionBegin; 3043552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30444f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30468e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 30473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3048552f7358SJed Brown } 3049552f7358SJed Brown 30500ce7577fSVaclav Hapla /*@C 30510ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30520ce7577fSVaclav Hapla 3053a1cb98faSBarry Smith Not Collective 30540ce7577fSVaclav Hapla 30550ce7577fSVaclav Hapla Input Parameters: 3056a1cb98faSBarry Smith + dm - The `DMPLEX` 3057a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30580ce7577fSVaclav Hapla 3059d8d19677SJose E. Roman Output Parameters: 306020f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 306120f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30620ce7577fSVaclav Hapla 30630ce7577fSVaclav Hapla Level: intermediate 30640ce7577fSVaclav Hapla 30651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30660ce7577fSVaclav Hapla @*/ 3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3068d71ae5a4SJacob Faibussowitsch { 30690ce7577fSVaclav Hapla PetscSection cs, newcs; 30700ce7577fSVaclav Hapla PetscInt *cones; 30710ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30720ce7577fSVaclav Hapla PetscInt n; 30730ce7577fSVaclav Hapla 30740ce7577fSVaclav Hapla PetscFunctionBegin; 30759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30779566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30780ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30790ce7577fSVaclav Hapla if (pCones) { 30809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30820ce7577fSVaclav Hapla } 30833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30840ce7577fSVaclav Hapla } 30850ce7577fSVaclav Hapla 3086af9eab45SVaclav Hapla /*@ 3087af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3088d4636a37SVaclav Hapla 3089a1cb98faSBarry Smith Not Collective 3090d4636a37SVaclav Hapla 3091d4636a37SVaclav Hapla Input Parameters: 3092a1cb98faSBarry Smith + dm - The `DMPLEX` 3093a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3094d4636a37SVaclav Hapla 3095d4636a37SVaclav Hapla Output Parameter: 3096af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3097d4636a37SVaclav Hapla 3098d4636a37SVaclav Hapla Level: advanced 3099d4636a37SVaclav Hapla 3100af9eab45SVaclav Hapla Notes: 310120f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3102af9eab45SVaclav Hapla 3103a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3104a1cb98faSBarry Smith 31051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3106a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3107d4636a37SVaclav Hapla @*/ 3108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3109d71ae5a4SJacob Faibussowitsch { 3110af9eab45SVaclav Hapla IS *expandedPointsAll; 3111af9eab45SVaclav Hapla PetscInt depth; 3112d4636a37SVaclav Hapla 3113d4636a37SVaclav Hapla PetscFunctionBegin; 3114af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3115af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31164f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 31179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3118af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 31199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 31209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 31213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3122af9eab45SVaclav Hapla } 3123af9eab45SVaclav Hapla 3124af9eab45SVaclav Hapla /*@ 3125af9eab45SVaclav Hapla DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones). 3126af9eab45SVaclav Hapla 3127a1cb98faSBarry Smith Not Collective 3128af9eab45SVaclav Hapla 3129af9eab45SVaclav Hapla Input Parameters: 3130a1cb98faSBarry Smith + dm - The `DMPLEX` 3131a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3132af9eab45SVaclav Hapla 3133d8d19677SJose E. Roman Output Parameters: 3134a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3135af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3136af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3137af9eab45SVaclav Hapla 3138af9eab45SVaclav Hapla Level: advanced 3139af9eab45SVaclav Hapla 3140af9eab45SVaclav Hapla Notes: 3141a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3142af9eab45SVaclav Hapla 3143a4e35b19SJacob Faibussowitsch Array `expandedPoints` has size equal to `depth`. Each `expandedPoints`[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points. 3144af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3145af9eab45SVaclav Hapla 3146a4e35b19SJacob Faibussowitsch Array section has size equal to `depth`. Each `PetscSection` `sections`[d] realizes mapping from `expandedPoints`[d+1] (section points) to `expandedPoints`[d] (section dofs) as follows\: 3147a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3148a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3149af9eab45SVaclav Hapla 31501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3151a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3152af9eab45SVaclav Hapla @*/ 3153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3154d71ae5a4SJacob Faibussowitsch { 3155af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3156af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3157af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3158af9eab45SVaclav Hapla IS *expandedPoints_; 3159af9eab45SVaclav Hapla PetscSection *sections_; 3160af9eab45SVaclav Hapla 3161af9eab45SVaclav Hapla PetscFunctionBegin; 3162af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3163af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31644f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31654f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31664f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3172af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3173af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3176af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3178af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3181af9eab45SVaclav Hapla } else { 31829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3183af9eab45SVaclav Hapla } 3184af9eab45SVaclav Hapla } 31859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3188af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3191af9eab45SVaclav Hapla if (cn > 1) { 31929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31939566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3194af9eab45SVaclav Hapla } else { 3195af9eab45SVaclav Hapla newarr[co] = arr[i]; 3196af9eab45SVaclav Hapla } 3197af9eab45SVaclav Hapla } 31989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3199af9eab45SVaclav Hapla arr = newarr; 3200af9eab45SVaclav Hapla n = newn; 3201af9eab45SVaclav Hapla } 32029566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3203af9eab45SVaclav Hapla *depth = depth_; 3204af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3205af9eab45SVaclav Hapla else { 32069566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32079566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3208af9eab45SVaclav Hapla } 3209af9eab45SVaclav Hapla if (sections) *sections = sections_; 3210af9eab45SVaclav Hapla else { 32119566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32129566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3213af9eab45SVaclav Hapla } 32143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3215af9eab45SVaclav Hapla } 3216af9eab45SVaclav Hapla 3217af9eab45SVaclav Hapla /*@ 3218a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3219af9eab45SVaclav Hapla 3220a1cb98faSBarry Smith Not Collective 3221af9eab45SVaclav Hapla 3222af9eab45SVaclav Hapla Input Parameters: 3223a1cb98faSBarry Smith + dm - The `DMPLEX` 3224a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3225af9eab45SVaclav Hapla 3226d8d19677SJose E. Roman Output Parameters: 3227a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3228af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3229af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3230af9eab45SVaclav Hapla 3231af9eab45SVaclav Hapla Level: advanced 3232af9eab45SVaclav Hapla 3233a1cb98faSBarry Smith Note: 3234a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3235af9eab45SVaclav Hapla 32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3237a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3238af9eab45SVaclav Hapla @*/ 3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3240d71ae5a4SJacob Faibussowitsch { 3241af9eab45SVaclav Hapla PetscInt d, depth_; 3242af9eab45SVaclav Hapla 3243af9eab45SVaclav Hapla PetscFunctionBegin; 32449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32451dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3246af9eab45SVaclav Hapla if (depth) *depth = 0; 3247af9eab45SVaclav Hapla if (expandedPoints) { 32489566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32499566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3250af9eab45SVaclav Hapla } 3251af9eab45SVaclav Hapla if (sections) { 32529566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32539566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3254af9eab45SVaclav Hapla } 32553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3256d4636a37SVaclav Hapla } 3257d4636a37SVaclav Hapla 3258552f7358SJed Brown /*@ 325992371b87SBarry Smith DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point 3260552f7358SJed Brown 3261a1cb98faSBarry Smith Not Collective 3262552f7358SJed Brown 3263552f7358SJed Brown Input Parameters: 326460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3265a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 326620f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3267552f7358SJed Brown 3268552f7358SJed Brown Level: beginner 3269552f7358SJed Brown 3270a1cb98faSBarry Smith Note: 3271a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3272a1cb98faSBarry Smith 32731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3274552f7358SJed Brown @*/ 3275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3276d71ae5a4SJacob Faibussowitsch { 3277552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3278552f7358SJed Brown PetscInt dof, off, c; 3279552f7358SJed Brown 3280552f7358SJed Brown PetscFunctionBegin; 3281552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32834f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3285db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3286db485b19SStefano Zampini PetscInt pStart, pEnd; 3287db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 328863a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3289552f7358SJed Brown for (c = 0; c < dof; ++c) { 329063a3b9bcSJacob Faibussowitsch PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd); 3291552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3292552f7358SJed Brown } 3293db485b19SStefano Zampini } else { 3294db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3295db485b19SStefano Zampini } 32963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3297552f7358SJed Brown } 3298552f7358SJed Brown 3299552f7358SJed Brown /*@C 3300eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3301552f7358SJed Brown 3302a1cb98faSBarry Smith Not Collective 3303552f7358SJed Brown 3304552f7358SJed Brown Input Parameters: 330560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3306a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3307552f7358SJed Brown 3308552f7358SJed Brown Output Parameter: 330920f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3310b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3311552f7358SJed Brown 3312552f7358SJed Brown Level: beginner 3313552f7358SJed Brown 3314a1cb98faSBarry Smith Note: 3315b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3316b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3317a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3318b5a892a1SMatthew G. Knepley with the identity. 3319b5a892a1SMatthew G. Knepley 332060225df5SJacob Faibussowitsch Fortran Notes: 3321a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3322a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 33233813dfbdSMatthew G Knepley 33241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3325552f7358SJed Brown @*/ 3326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3327d71ae5a4SJacob Faibussowitsch { 3328552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3329552f7358SJed Brown PetscInt off; 3330552f7358SJed Brown 3331552f7358SJed Brown PetscFunctionBegin; 3332552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3334552f7358SJed Brown PetscInt dof; 33359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33364f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3337552f7358SJed Brown } 33389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33390d644c17SKarl Rupp 3340552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3342552f7358SJed Brown } 3343552f7358SJed Brown 3344552f7358SJed Brown /*@ 3345eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3346552f7358SJed Brown 3347a1cb98faSBarry Smith Not Collective 3348552f7358SJed Brown 3349552f7358SJed Brown Input Parameters: 335060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3351a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3352b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3353b5a892a1SMatthew G. Knepley 3354552f7358SJed Brown Level: beginner 3355552f7358SJed Brown 3356a1cb98faSBarry Smith Notes: 3357a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3358a1cb98faSBarry Smith 3359a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3360a1cb98faSBarry Smith 33611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3362552f7358SJed Brown @*/ 3363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3364d71ae5a4SJacob Faibussowitsch { 3365552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3366552f7358SJed Brown PetscInt pStart, pEnd; 3367552f7358SJed Brown PetscInt dof, off, c; 3368552f7358SJed Brown 3369552f7358SJed Brown PetscFunctionBegin; 3370552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33724f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3374db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3375db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 337663a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3377552f7358SJed Brown for (c = 0; c < dof; ++c) { 3378552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3379552f7358SJed Brown 33809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33811dca8a05SBarry Smith PetscCheck(!o || (o >= -(cdof + 1) && o < cdof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof + 1), cdof); 3382552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3383552f7358SJed Brown } 3384db485b19SStefano Zampini } else { 3385db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3386db485b19SStefano Zampini } 33873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3388552f7358SJed Brown } 3389552f7358SJed Brown 33907cd05799SMatthew G. Knepley /*@ 3391eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33927cd05799SMatthew G. Knepley 3393a1cb98faSBarry Smith Not Collective 33947cd05799SMatthew G. Knepley 33957cd05799SMatthew G. Knepley Input Parameters: 339660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3397a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33987cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 33997cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 34007cd05799SMatthew G. Knepley 34017cd05799SMatthew G. Knepley Level: beginner 34027cd05799SMatthew G. Knepley 34031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34047cd05799SMatthew G. Knepley @*/ 3405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3406d71ae5a4SJacob Faibussowitsch { 3407552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3408552f7358SJed Brown PetscInt pStart, pEnd; 3409552f7358SJed Brown PetscInt dof, off; 3410552f7358SJed Brown 3411552f7358SJed Brown PetscFunctionBegin; 3412552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3413a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 341563a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 341663a3b9bcSJacob Faibussowitsch PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd); 34179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 341863a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3419a03d55ffSStefano Zampini } 3420a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3421552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 34223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3423552f7358SJed Brown } 3424552f7358SJed Brown 34257cd05799SMatthew G. Knepley /*@ 3426eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 34277cd05799SMatthew G. Knepley 3428a1cb98faSBarry Smith Not Collective 34297cd05799SMatthew G. Knepley 34307cd05799SMatthew G. Knepley Input Parameters: 343160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3432a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34337cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34347cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34357cd05799SMatthew G. Knepley 34367cd05799SMatthew G. Knepley Level: beginner 34377cd05799SMatthew G. Knepley 3438a1cb98faSBarry Smith Note: 3439a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3440b5a892a1SMatthew G. Knepley 34411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34427cd05799SMatthew G. Knepley @*/ 3443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3444d71ae5a4SJacob Faibussowitsch { 344577c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 344677c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 344777c88f5bSMatthew G Knepley PetscInt dof, off; 344877c88f5bSMatthew G Knepley 344977c88f5bSMatthew G Knepley PetscFunctionBegin; 345077c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3451a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345363a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 34549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 345563a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3456a03d55ffSStefano Zampini } 3457a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 345877c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346077c88f5bSMatthew G Knepley } 346177c88f5bSMatthew G Knepley 34629f4ada15SMatthew G. Knepley /*@C 34639f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34649f4ada15SMatthew G. Knepley 34659f4ada15SMatthew G. Knepley Not collective 34669f4ada15SMatthew G. Knepley 34679f4ada15SMatthew G. Knepley Input Parameters: 34689f4ada15SMatthew G. Knepley + dm - The DMPlex 34699f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34709f4ada15SMatthew G. Knepley 34719f4ada15SMatthew G. Knepley Output Parameters: 347220f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 347320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34749f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34759f4ada15SMatthew G. Knepley 34769f4ada15SMatthew G. Knepley Level: beginner 34779f4ada15SMatthew G. Knepley 34789f4ada15SMatthew G. Knepley Notes: 34799f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34809f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 348120f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34829f4ada15SMatthew G. Knepley with the identity. 34839f4ada15SMatthew G. Knepley 34849f4ada15SMatthew G. Knepley Fortran Notes: 348520f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 348620f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34879f4ada15SMatthew G. Knepley 34881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34899f4ada15SMatthew G. Knepley @*/ 34909f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34919f4ada15SMatthew G. Knepley { 34929f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34939f4ada15SMatthew G. Knepley 34949f4ada15SMatthew G. Knepley PetscFunctionBegin; 34959f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34969f4ada15SMatthew G. Knepley if (mesh->tr) { 34979f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34989f4ada15SMatthew G. Knepley } else { 34999f4ada15SMatthew G. Knepley PetscInt off; 35009f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 35019f4ada15SMatthew G. Knepley PetscInt dof; 35029f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35039f4ada15SMatthew G. Knepley if (dof) { 35044f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 35054f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35069f4ada15SMatthew G. Knepley } 35079f4ada15SMatthew G. Knepley } 35089f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35098e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 35108e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 35119f4ada15SMatthew G. Knepley } 35123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35139f4ada15SMatthew G. Knepley } 35149f4ada15SMatthew G. Knepley 35159f4ada15SMatthew G. Knepley /*@C 35169f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 35179f4ada15SMatthew G. Knepley 351820f4b53cSBarry Smith Not Collective 35199f4ada15SMatthew G. Knepley 35209f4ada15SMatthew G. Knepley Input Parameters: 35219f4ada15SMatthew G. Knepley + dm - The DMPlex 352220f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35239f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 352420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35259f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35269f4ada15SMatthew G. Knepley 35279f4ada15SMatthew G. Knepley Level: beginner 35289f4ada15SMatthew G. Knepley 35299f4ada15SMatthew G. Knepley Notes: 35309f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35319f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 353220f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35339f4ada15SMatthew G. Knepley with the identity. 35349f4ada15SMatthew G. Knepley 353560225df5SJacob Faibussowitsch Fortran Notes: 353620f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 353720f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35389f4ada15SMatthew G. Knepley 35391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35409f4ada15SMatthew G. Knepley @*/ 35419f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35429f4ada15SMatthew G. Knepley { 35439f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35449f4ada15SMatthew G. Knepley 35459f4ada15SMatthew G. Knepley PetscFunctionBegin; 35469f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35479f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35499f4ada15SMatthew G. Knepley } 35509f4ada15SMatthew G. Knepley 3551552f7358SJed Brown /*@ 3552eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3553552f7358SJed Brown 3554a1cb98faSBarry Smith Not Collective 3555552f7358SJed Brown 3556552f7358SJed Brown Input Parameters: 355760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3558a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3559552f7358SJed Brown 3560552f7358SJed Brown Output Parameter: 356120f4b53cSBarry Smith . size - The support size for point `p` 3562552f7358SJed Brown 3563552f7358SJed Brown Level: beginner 3564552f7358SJed Brown 35651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3566552f7358SJed Brown @*/ 3567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3568d71ae5a4SJacob Faibussowitsch { 3569552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3570552f7358SJed Brown 3571552f7358SJed Brown PetscFunctionBegin; 3572552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35734f572ea9SToby Isaac PetscAssertPointer(size, 3); 35749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3576552f7358SJed Brown } 3577552f7358SJed Brown 3578552f7358SJed Brown /*@ 3579eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3580552f7358SJed Brown 3581a1cb98faSBarry Smith Not Collective 3582552f7358SJed Brown 3583552f7358SJed Brown Input Parameters: 358460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3585a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 358620f4b53cSBarry Smith - size - The support size for point `p` 3587552f7358SJed Brown 3588a1cb98faSBarry Smith Level: beginner 3589552f7358SJed Brown 3590552f7358SJed Brown Note: 359120f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3592552f7358SJed Brown 35931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3594552f7358SJed Brown @*/ 3595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3596d71ae5a4SJacob Faibussowitsch { 3597552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3598552f7358SJed Brown 3599552f7358SJed Brown PetscFunctionBegin; 3600552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 36023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3603552f7358SJed Brown } 3604552f7358SJed Brown 3605552f7358SJed Brown /*@C 3606eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3607552f7358SJed Brown 3608a1cb98faSBarry Smith Not Collective 3609552f7358SJed Brown 3610552f7358SJed Brown Input Parameters: 361160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3612a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3613552f7358SJed Brown 3614552f7358SJed Brown Output Parameter: 361520f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3616552f7358SJed Brown 3617552f7358SJed Brown Level: beginner 3618552f7358SJed Brown 361960225df5SJacob Faibussowitsch Fortran Notes: 3620a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3621a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 36223813dfbdSMatthew G Knepley 36231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3624552f7358SJed Brown @*/ 3625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3626d71ae5a4SJacob Faibussowitsch { 3627552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3628552f7358SJed Brown PetscInt off; 3629552f7358SJed Brown 3630552f7358SJed Brown PetscFunctionBegin; 3631552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36324f572ea9SToby Isaac PetscAssertPointer(support, 3); 36339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 36348e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 36353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3636552f7358SJed Brown } 3637552f7358SJed Brown 3638552f7358SJed Brown /*@ 363992371b87SBarry Smith DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3640552f7358SJed Brown 3641a1cb98faSBarry Smith Not Collective 3642552f7358SJed Brown 3643552f7358SJed Brown Input Parameters: 364460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3645a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 364620f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3647552f7358SJed Brown 3648552f7358SJed Brown Level: beginner 3649552f7358SJed Brown 3650a1cb98faSBarry Smith Note: 3651a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3652a1cb98faSBarry Smith 36531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3654552f7358SJed Brown @*/ 3655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3656d71ae5a4SJacob Faibussowitsch { 3657552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3658552f7358SJed Brown PetscInt pStart, pEnd; 3659552f7358SJed Brown PetscInt dof, off, c; 3660552f7358SJed Brown 3661552f7358SJed Brown PetscFunctionBegin; 3662552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36654f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 366763a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3668552f7358SJed Brown for (c = 0; c < dof; ++c) { 366963a3b9bcSJacob Faibussowitsch PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd); 3670552f7358SJed Brown mesh->supports[off + c] = support[c]; 3671552f7358SJed Brown } 36723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3673552f7358SJed Brown } 3674552f7358SJed Brown 36757cd05799SMatthew G. Knepley /*@ 3676eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36777cd05799SMatthew G. Knepley 3678a1cb98faSBarry Smith Not Collective 36797cd05799SMatthew G. Knepley 36807cd05799SMatthew G. Knepley Input Parameters: 368160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3682a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36837cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36847cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36857cd05799SMatthew G. Knepley 36867cd05799SMatthew G. Knepley Level: beginner 36877cd05799SMatthew G. Knepley 36881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36897cd05799SMatthew G. Knepley @*/ 3690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3691d71ae5a4SJacob Faibussowitsch { 3692552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3693552f7358SJed Brown PetscInt pStart, pEnd; 3694552f7358SJed Brown PetscInt dof, off; 3695552f7358SJed Brown 3696552f7358SJed Brown PetscFunctionBegin; 3697552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 370163a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 370263a3b9bcSJacob Faibussowitsch PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd); 370363a3b9bcSJacob Faibussowitsch PetscCheck(supportPos < dof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof); 3704552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 37053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3706552f7358SJed Brown } 3707552f7358SJed Brown 3708b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3709d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3710d71ae5a4SJacob Faibussowitsch { 3711b5a892a1SMatthew G. Knepley switch (ct) { 3712b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3713b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3714b5a892a1SMatthew G. Knepley break; 3715b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3716b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3717b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3718b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3719b5a892a1SMatthew G. Knepley break; 3720b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3721b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3722b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3723b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3724b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3725b5a892a1SMatthew G. Knepley break; 3726d71ae5a4SJacob Faibussowitsch default: 3727d71ae5a4SJacob Faibussowitsch return o; 3728b5a892a1SMatthew G. Knepley } 3729b5a892a1SMatthew G. Knepley return o; 3730b5a892a1SMatthew G. Knepley } 3731b5a892a1SMatthew G. Knepley 3732b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3733d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3734d71ae5a4SJacob Faibussowitsch { 3735b5a892a1SMatthew G. Knepley switch (ct) { 3736b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3737b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3738b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3739b5a892a1SMatthew G. Knepley break; 3740b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3741b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3742b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3743b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3744b5a892a1SMatthew G. Knepley break; 3745b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3746b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3747b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3748b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3749b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3750b5a892a1SMatthew G. Knepley break; 3751d71ae5a4SJacob Faibussowitsch default: 3752d71ae5a4SJacob Faibussowitsch return o; 3753b5a892a1SMatthew G. Knepley } 3754b5a892a1SMatthew G. Knepley return o; 3755b5a892a1SMatthew G. Knepley } 3756b5a892a1SMatthew G. Knepley 3757b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3759d71ae5a4SJacob Faibussowitsch { 3760b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3761b5a892a1SMatthew G. Knepley 3762b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3764b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3765b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3766b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3767b5a892a1SMatthew G. Knepley 37689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3771b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3772b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3773b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3774b5a892a1SMatthew G. Knepley 37759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3776b5a892a1SMatthew G. Knepley switch (ct) { 3777b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37789566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37799566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3780b5a892a1SMatthew G. Knepley break; 3781b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37829566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37839566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37849566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3785b5a892a1SMatthew G. Knepley break; 3786b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37879566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37889566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37899566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37909566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3791b5a892a1SMatthew G. Knepley break; 3792d71ae5a4SJacob Faibussowitsch default: 3793d71ae5a4SJacob Faibussowitsch break; 3794b5a892a1SMatthew G. Knepley } 3795b5a892a1SMatthew G. Knepley } 3796b5a892a1SMatthew G. Knepley } 37973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3798b5a892a1SMatthew G. Knepley } 3799b5a892a1SMatthew G. Knepley 380009015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 380109015e70SStefano Zampini { 380209015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 380309015e70SStefano Zampini 380409015e70SStefano Zampini PetscFunctionBeginHot; 380509015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 380609015e70SStefano Zampini if (useCone) { 380709015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 380809015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 380909015e70SStefano Zampini } else { 381009015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 381109015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 381209015e70SStefano Zampini } 381309015e70SStefano Zampini } else { 381409015e70SStefano Zampini if (useCone) { 381509015e70SStefano Zampini const PetscSection s = mesh->coneSection; 381609015e70SStefano Zampini const PetscInt ps = p - s->pStart; 381709015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 381809015e70SStefano Zampini 381909015e70SStefano Zampini *size = s->atlasDof[ps]; 382009015e70SStefano Zampini *arr = mesh->cones + off; 382109015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 382209015e70SStefano Zampini } else { 382309015e70SStefano Zampini const PetscSection s = mesh->supportSection; 382409015e70SStefano Zampini const PetscInt ps = p - s->pStart; 382509015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 382609015e70SStefano Zampini 382709015e70SStefano Zampini *size = s->atlasDof[ps]; 382809015e70SStefano Zampini *arr = mesh->supports + off; 382909015e70SStefano Zampini } 383009015e70SStefano Zampini } 383109015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 383209015e70SStefano Zampini } 383309015e70SStefano Zampini 383409015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 383509015e70SStefano Zampini { 383609015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 383709015e70SStefano Zampini 383809015e70SStefano Zampini PetscFunctionBeginHot; 383909015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 384009015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 384109015e70SStefano Zampini } 384209015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 384309015e70SStefano Zampini } 384409015e70SStefano Zampini 3845d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3846d71ae5a4SJacob Faibussowitsch { 3847b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3848b5a892a1SMatthew G. Knepley PetscInt *closure; 3849b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3850b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3851b5a892a1SMatthew G. Knepley 3852b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3853b5a892a1SMatthew G. Knepley if (ornt) { 38549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3855476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3856b5a892a1SMatthew G. Knepley } 3857b5a892a1SMatthew G. Knepley if (*points) { 3858b5a892a1SMatthew G. Knepley closure = *points; 3859b5a892a1SMatthew G. Knepley } else { 3860b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38619566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3863b5a892a1SMatthew G. Knepley } 386409015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3865b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3866b5a892a1SMatthew G. Knepley closure[off++] = p; 3867b5a892a1SMatthew G. Knepley closure[off++] = 0; 3868b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3869b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3870b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3871b5a892a1SMatthew G. Knepley } 3872b5a892a1SMatthew G. Knepley } else { 387385036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3874b5a892a1SMatthew G. Knepley 3875b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3876b5a892a1SMatthew G. Knepley closure[off++] = p; 3877b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3878b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3879b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3880b5a892a1SMatthew G. Knepley 38819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3882b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3883b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3884b5a892a1SMatthew G. Knepley } 3885b5a892a1SMatthew G. Knepley } 388609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3887b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3888b5a892a1SMatthew G. Knepley if (points) *points = closure; 38893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3890b5a892a1SMatthew G. Knepley } 3891b5a892a1SMatthew G. Knepley 3892d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3894d71ae5a4SJacob Faibussowitsch { 389585036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3896b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3897b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3898b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3899b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3900b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3901b5a892a1SMatthew G. Knepley 3902b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 390409015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 39059566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3906b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3907b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3908b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39099371c9d4SSatish Balay if (*points) { 39109371c9d4SSatish Balay pts = *points; 39119371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3912b5a892a1SMatthew G. Knepley c = 0; 3913b5a892a1SMatthew G. Knepley pts[c++] = point; 3914b5a892a1SMatthew G. Knepley pts[c++] = o; 39159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 39169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 39179371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39189371c9d4SSatish Balay pts[c++] = closure[cl]; 39199371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39209371c9d4SSatish Balay } 39219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 39229371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39239371c9d4SSatish Balay pts[c++] = closure[cl]; 39249371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39259371c9d4SSatish Balay } 39269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3927b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 39289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3929b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3930b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3931b5a892a1SMatthew G. Knepley } 393209015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3933b5a892a1SMatthew G. Knepley if (dim >= 3) { 3934b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3935b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3936b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3937b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3938b5a892a1SMatthew G. Knepley 39399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 394085036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 394109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3942b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3943b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3944b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3945b5a892a1SMatthew G. Knepley 39469371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39479371c9d4SSatish Balay if (pts[i] == cp) break; 3948b5a892a1SMatthew G. Knepley if (i == c) { 39499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3950b5a892a1SMatthew G. Knepley pts[c++] = cp; 3951b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3952b5a892a1SMatthew G. Knepley } 3953b5a892a1SMatthew G. Knepley } 395409015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3955b5a892a1SMatthew G. Knepley } 3956b5a892a1SMatthew G. Knepley } 3957b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3958b5a892a1SMatthew G. Knepley *points = pts; 39593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3960b5a892a1SMatthew G. Knepley } 3961b5a892a1SMatthew G. Knepley 3962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3963d71ae5a4SJacob Faibussowitsch { 3964b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3965b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3966b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3967b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3968b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3969b5a892a1SMatthew G. Knepley 3970b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3972b5a892a1SMatthew G. Knepley if (depth == 1) { 39739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3975b5a892a1SMatthew G. Knepley } 39769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3977476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3978c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39799566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3981b5a892a1SMatthew G. Knepley } 39829566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3983b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3984b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3985b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39879371c9d4SSatish Balay if (*points) { 39889371c9d4SSatish Balay closure = *points; 39899371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3990b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3991b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3992b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3993b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3994b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3995b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3996b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3997b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3998b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3999b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 400085036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 400109015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4002b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4003b5a892a1SMatthew G. Knepley 4004b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 400585036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 400663a3b9bcSJacob Faibussowitsch PetscCheck(!o || !(o >= nO || o < -nO), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q); 4007b5a892a1SMatthew G. Knepley } 400809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4009b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4010b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4011b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4012b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 40139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4014b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4015b5a892a1SMatthew G. Knepley PetscInt c; 4016b5a892a1SMatthew G. Knepley 4017b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4018b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4019b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4020b5a892a1SMatthew G. Knepley } 4021b5a892a1SMatthew G. Knepley if (c == closureSize) { 4022b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4023b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4024b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4025b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4026b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4027b5a892a1SMatthew G. Knepley } 4028b5a892a1SMatthew G. Knepley } 402909015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4030b5a892a1SMatthew G. Knepley } 40319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4032b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4033b5a892a1SMatthew G. Knepley if (points) *points = closure; 40343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4035b5a892a1SMatthew G. Knepley } 4036b5a892a1SMatthew G. Knepley 4037552f7358SJed Brown /*@C 4038eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4039552f7358SJed Brown 4040a1cb98faSBarry Smith Not Collective 4041552f7358SJed Brown 4042552f7358SJed Brown Input Parameters: 4043a1cb98faSBarry Smith + dm - The `DMPLEX` 4044b5a892a1SMatthew G. Knepley . p - The mesh point 4045a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4046552f7358SJed Brown 40476b867d5aSJose E. Roman Input/Output Parameter: 40486b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 404920f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40506b867d5aSJose E. Roman 40516b867d5aSJose E. Roman Output Parameter: 405220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4053552f7358SJed Brown 4054a1cb98faSBarry Smith Level: beginner 4055a1cb98faSBarry Smith 4056552f7358SJed Brown Note: 405720f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4058552f7358SJed Brown 405960225df5SJacob Faibussowitsch Fortran Notes: 406020f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40613813dfbdSMatthew G Knepley 40621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4063552f7358SJed Brown @*/ 4064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4065d71ae5a4SJacob Faibussowitsch { 4066b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4067552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40684f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40694f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40729bf0dad6SMatthew G. Knepley } 40739bf0dad6SMatthew G. Knepley 4074552f7358SJed Brown /*@C 4075eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4076552f7358SJed Brown 4077a1cb98faSBarry Smith Not Collective 4078552f7358SJed Brown 4079552f7358SJed Brown Input Parameters: 4080a1cb98faSBarry Smith + dm - The `DMPLEX` 4081b5a892a1SMatthew G. Knepley . p - The mesh point 4082a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 408320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4084b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4085552f7358SJed Brown 4086a1cb98faSBarry Smith Level: beginner 4087a1cb98faSBarry Smith 4088552f7358SJed Brown Note: 408920f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4090552f7358SJed Brown 40911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4092552f7358SJed Brown @*/ 4093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4094d71ae5a4SJacob Faibussowitsch { 4095b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4096552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40974ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40989566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 40993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4100552f7358SJed Brown } 4101552f7358SJed Brown 4102552f7358SJed Brown /*@ 4103eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4104552f7358SJed Brown 4105a1cb98faSBarry Smith Not Collective 4106552f7358SJed Brown 4107552f7358SJed Brown Input Parameter: 410860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4109552f7358SJed Brown 4110552f7358SJed Brown Output Parameters: 4111552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4112552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4113552f7358SJed Brown 4114552f7358SJed Brown Level: beginner 4115552f7358SJed Brown 41161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4117552f7358SJed Brown @*/ 4118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4119d71ae5a4SJacob Faibussowitsch { 4120552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4121552f7358SJed Brown 4122552f7358SJed Brown PetscFunctionBegin; 4123552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41241baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 41251baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 41263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4127552f7358SJed Brown } 4128552f7358SJed Brown 4129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4130d71ae5a4SJacob Faibussowitsch { 4131552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 41326302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4133552f7358SJed Brown 4134552f7358SJed Brown PetscFunctionBegin; 4135552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41406302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41416302a7fbSVaclav Hapla if (maxSupportSize) { 41429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4145552f7358SJed Brown } 41463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4147552f7358SJed Brown } 4148552f7358SJed Brown 4149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4150d71ae5a4SJacob Faibussowitsch { 4151552f7358SJed Brown PetscFunctionBegin; 41529566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4153dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4154ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4155736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 415695602cf2SAlexis Marboeuf PetscSF sfNatural; 4157f94b4a02SBlaise Bourdin 41583dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 416095602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4161c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4162f94b4a02SBlaise Bourdin } 41633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4164552f7358SJed Brown } 4165552f7358SJed Brown 4166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4167d71ae5a4SJacob Faibussowitsch { 41683dcd263cSBlaise Bourdin PetscInt i = 0; 41692adcc780SMatthew G. Knepley 41702adcc780SMatthew G. Knepley PetscFunctionBegin; 41719566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41729566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4173c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41743dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41753dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 417695602cf2SAlexis Marboeuf PetscSF sfNatural; 41773dcd263cSBlaise Bourdin 41783dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4180c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 418195602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4182c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41833dcd263cSBlaise Bourdin break; 41843dcd263cSBlaise Bourdin } 41853dcd263cSBlaise Bourdin } 41863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41872adcc780SMatthew G. Knepley } 41882adcc780SMatthew G. Knepley 4189552f7358SJed Brown /*@ 4190eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4191552f7358SJed Brown 4192a1cb98faSBarry Smith Not Collective 4193552f7358SJed Brown 4194552f7358SJed Brown Input Parameter: 419560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4196552f7358SJed Brown 4197552f7358SJed Brown Level: beginner 4198552f7358SJed Brown 4199a1cb98faSBarry Smith Note: 4200a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4201a1cb98faSBarry Smith 42021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4203552f7358SJed Brown @*/ 4204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4205d71ae5a4SJacob Faibussowitsch { 4206552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4207552f7358SJed Brown PetscInt *offsets; 4208552f7358SJed Brown PetscInt supportSize; 4209552f7358SJed Brown PetscInt pStart, pEnd, p; 4210552f7358SJed Brown 4211552f7358SJed Brown PetscFunctionBegin; 4212552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 421328b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 42149566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4215552f7358SJed Brown /* Calculate support sizes */ 42169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4217552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4218552f7358SJed Brown PetscInt dof, off, c; 4219552f7358SJed Brown 42209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 422248a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4223552f7358SJed Brown } 42249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4225552f7358SJed Brown /* Calculate supports */ 42269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 42279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 42289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4229552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4230552f7358SJed Brown PetscInt dof, off, c; 4231552f7358SJed Brown 42329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4234552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4235552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4236552f7358SJed Brown PetscInt offS; 4237552f7358SJed Brown 42389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42390d644c17SKarl Rupp 4240552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4241552f7358SJed Brown ++offsets[q]; 4242552f7358SJed Brown } 4243552f7358SJed Brown } 42449566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4247552f7358SJed Brown } 4248552f7358SJed Brown 4249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4250d71ae5a4SJacob Faibussowitsch { 4251277ea44aSLisandro Dalcin IS stratumIS; 4252277ea44aSLisandro Dalcin 4253277ea44aSLisandro Dalcin PetscFunctionBegin; 42543ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 425576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4256277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4257277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42589566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4259277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42609566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42619371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42629371c9d4SSatish Balay overlap = PETSC_TRUE; 42639371c9d4SSatish Balay break; 42649371c9d4SSatish Balay } 4265277ea44aSLisandro Dalcin } 426663a3b9bcSJacob Faibussowitsch PetscCheck(!overlap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd); 4267277ea44aSLisandro Dalcin } 42689566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42699566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4272277ea44aSLisandro Dalcin } 4273277ea44aSLisandro Dalcin 4274e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4275e91fa0a1SMatthew G. Knepley { 4276e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4277e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4278e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4279e91fa0a1SMatthew G. Knepley 4280e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4281e91fa0a1SMatthew G. Knepley { 4282e91fa0a1SMatthew G. Knepley DMLabel label2; 4283e91fa0a1SMatthew G. Knepley 4284e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4285e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4286e91fa0a1SMatthew G. Knepley } 4287e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4288e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4289e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4290e91fa0a1SMatthew G. Knepley 4291e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4292e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4293e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4294e91fa0a1SMatthew G. Knepley } 4295e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4296e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4297e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4298e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4299e91fa0a1SMatthew G. Knepley } 4300e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4301e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4302e91fa0a1SMatthew G. Knepley PetscInt d; 4303e91fa0a1SMatthew G. Knepley 4304e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4305e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4306e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4307e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4308e91fa0a1SMatthew G. Knepley } 4309e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4310e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4311e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4312e91fa0a1SMatthew G. Knepley } 4313e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4314e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4315e91fa0a1SMatthew G. Knepley } 4316e91fa0a1SMatthew G. Knepley 4317e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4318e91fa0a1SMatthew G. Knepley { 4319e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4320e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4321e91fa0a1SMatthew G. Knepley 4322e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4323e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4324e91fa0a1SMatthew G. Knepley { 4325e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4326e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4327e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4328e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4329e91fa0a1SMatthew G. Knepley 4330e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4331e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4332e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4333e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4334e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4335e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4336e91fa0a1SMatthew G. Knepley ++numRoots; 4337e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4338e91fa0a1SMatthew G. Knepley ++numLeaves; 4339e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4340e91fa0a1SMatthew G. Knepley /* Isolated points */ 4341e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4342e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4343e91fa0a1SMatthew G. Knepley } 4344e91fa0a1SMatthew G. Knepley } 4345e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4346e91fa0a1SMatthew G. Knepley } 4347e91fa0a1SMatthew G. Knepley 4348e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4349e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4350e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4351e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4352e91fa0a1SMatthew G. Knepley 4353e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4354e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4355e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4356e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4357e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4358e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4359e91fa0a1SMatthew G. Knepley } 4360e91fa0a1SMatthew G. Knepley } 4361e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4362e91fa0a1SMatthew G. Knepley } else { 4363e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4364e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4365e91fa0a1SMatthew G. Knepley 4366e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4367e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4368e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4369e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4370e91fa0a1SMatthew G. Knepley 4371e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4372e91fa0a1SMatthew G. Knepley const PetscInt *support; 4373e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4374e91fa0a1SMatthew G. Knepley 4375e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4376e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4377e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4378e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4379e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4380e91fa0a1SMatthew G. Knepley } 4381e91fa0a1SMatthew G. Knepley } 4382e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4383e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4384e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4385e91fa0a1SMatthew G. Knepley } 4386e91fa0a1SMatthew G. Knepley } 4387e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4388e91fa0a1SMatthew G. Knepley } 4389e91fa0a1SMatthew G. Knepley 4390552f7358SJed Brown /*@ 4391a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4392552f7358SJed Brown 439320f4b53cSBarry Smith Collective 4394552f7358SJed Brown 4395552f7358SJed Brown Input Parameter: 439660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4397552f7358SJed Brown 4398a1cb98faSBarry Smith Level: beginner 4399552f7358SJed Brown 4400552f7358SJed Brown Notes: 4401a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4402a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4403a4e35b19SJacob Faibussowitsch 4404a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4405a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4406a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4407b1bb481bSMatthew Knepley meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 4408a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4409a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4410a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4411552f7358SJed Brown 4412b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4413b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4414b1bb481bSMatthew Knepley we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose 4415b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4416a1cb98faSBarry Smith .vb 4417a1cb98faSBarry Smith cone(c0) = {e0, v2} 4418a1cb98faSBarry Smith cone(e0) = {v0, v1} 4419a1cb98faSBarry Smith .ve 4420a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4421a1cb98faSBarry Smith .vb 4422a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4423a1cb98faSBarry Smith depth 1 = {e0, c0} 4424a1cb98faSBarry Smith .ve 4425b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4426b1bb481bSMatthew Knepley 4427a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4428552f7358SJed Brown 44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4430552f7358SJed Brown @*/ 4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4432d71ae5a4SJacob Faibussowitsch { 4433df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4434aa50250dSMatthew G. Knepley DMLabel label; 4435e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4436552f7358SJed Brown 4437552f7358SJed Brown PetscFunctionBegin; 4438552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4440277ea44aSLisandro Dalcin 4441e91fa0a1SMatthew G. Knepley // Create depth label 4442*d28dd301SMatthew G. Knepley PetscCall(DMRemoveLabel(dm, "depth", NULL)); 44439566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4445277ea44aSLisandro Dalcin 4446e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4447e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4448e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4449552f7358SJed Brown 4450bf4602e4SToby Isaac { /* just in case there is an empty process */ 4451bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4452bf4602e4SToby Isaac 44539566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4454712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 445548a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4456bf4602e4SToby Isaac } 44579566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4460552f7358SJed Brown } 4461552f7358SJed Brown 4462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4463d71ae5a4SJacob Faibussowitsch { 4464412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4465412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4466ba2698f1SMatthew G. Knepley 4467412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4471ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4472ba2698f1SMatthew G. Knepley if (depth <= 1) { 4473ba2698f1SMatthew G. Knepley switch (pdepth) { 4474d71ae5a4SJacob Faibussowitsch case 0: 4475d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4476d71ae5a4SJacob Faibussowitsch break; 4477ba2698f1SMatthew G. Knepley case 1: 4478ba2698f1SMatthew G. Knepley switch (coneSize) { 4479d71ae5a4SJacob Faibussowitsch case 2: 4480d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4481d71ae5a4SJacob Faibussowitsch break; 4482d71ae5a4SJacob Faibussowitsch case 3: 4483d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4484d71ae5a4SJacob Faibussowitsch break; 4485ba2698f1SMatthew G. Knepley case 4: 4486ba2698f1SMatthew G. Knepley switch (dim) { 4487d71ae5a4SJacob Faibussowitsch case 2: 4488d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4489d71ae5a4SJacob Faibussowitsch break; 4490d71ae5a4SJacob Faibussowitsch case 3: 4491d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4492d71ae5a4SJacob Faibussowitsch break; 4493d71ae5a4SJacob Faibussowitsch default: 4494d71ae5a4SJacob Faibussowitsch break; 4495ba2698f1SMatthew G. Knepley } 4496ba2698f1SMatthew G. Knepley break; 4497d71ae5a4SJacob Faibussowitsch case 5: 4498d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4499d71ae5a4SJacob Faibussowitsch break; 4500d71ae5a4SJacob Faibussowitsch case 6: 4501d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4502d71ae5a4SJacob Faibussowitsch break; 4503d71ae5a4SJacob Faibussowitsch case 8: 4504d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4505d71ae5a4SJacob Faibussowitsch break; 4506d71ae5a4SJacob Faibussowitsch default: 4507d71ae5a4SJacob Faibussowitsch break; 4508ba2698f1SMatthew G. Knepley } 4509ba2698f1SMatthew G. Knepley } 4510ba2698f1SMatthew G. Knepley } else { 4511ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4512ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4513ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4514ba2698f1SMatthew G. Knepley switch (dim) { 4515ba2698f1SMatthew G. Knepley case 1: 4516ba2698f1SMatthew G. Knepley switch (coneSize) { 4517d71ae5a4SJacob Faibussowitsch case 2: 4518d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4519d71ae5a4SJacob Faibussowitsch break; 4520d71ae5a4SJacob Faibussowitsch default: 4521d71ae5a4SJacob Faibussowitsch break; 4522ba2698f1SMatthew G. Knepley } 4523ba2698f1SMatthew G. Knepley break; 4524ba2698f1SMatthew G. Knepley case 2: 4525ba2698f1SMatthew G. Knepley switch (coneSize) { 4526d71ae5a4SJacob Faibussowitsch case 3: 4527d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4528d71ae5a4SJacob Faibussowitsch break; 4529d71ae5a4SJacob Faibussowitsch case 4: 4530d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4531d71ae5a4SJacob Faibussowitsch break; 4532d71ae5a4SJacob Faibussowitsch default: 4533d71ae5a4SJacob Faibussowitsch break; 4534ba2698f1SMatthew G. Knepley } 4535ba2698f1SMatthew G. Knepley break; 4536ba2698f1SMatthew G. Knepley case 3: 4537ba2698f1SMatthew G. Knepley switch (coneSize) { 4538d71ae5a4SJacob Faibussowitsch case 4: 4539d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4540d71ae5a4SJacob Faibussowitsch break; 45419371c9d4SSatish Balay case 5: { 4542da9060c4SMatthew G. Knepley const PetscInt *cone; 4543da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4544da9060c4SMatthew G. Knepley 45459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4547da9060c4SMatthew G. Knepley switch (faceConeSize) { 4548d71ae5a4SJacob Faibussowitsch case 3: 4549d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4550d71ae5a4SJacob Faibussowitsch break; 4551d71ae5a4SJacob Faibussowitsch case 4: 4552d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4553d71ae5a4SJacob Faibussowitsch break; 4554da9060c4SMatthew G. Knepley } 45559371c9d4SSatish Balay } break; 4556d71ae5a4SJacob Faibussowitsch case 6: 4557d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4558d71ae5a4SJacob Faibussowitsch break; 4559d71ae5a4SJacob Faibussowitsch default: 4560d71ae5a4SJacob Faibussowitsch break; 4561ba2698f1SMatthew G. Knepley } 4562ba2698f1SMatthew G. Knepley break; 4563d71ae5a4SJacob Faibussowitsch default: 4564d71ae5a4SJacob Faibussowitsch break; 4565ba2698f1SMatthew G. Knepley } 4566ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4567ba2698f1SMatthew G. Knepley switch (coneSize) { 4568d71ae5a4SJacob Faibussowitsch case 2: 4569d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4570d71ae5a4SJacob Faibussowitsch break; 4571d71ae5a4SJacob Faibussowitsch case 3: 4572d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4573d71ae5a4SJacob Faibussowitsch break; 4574d71ae5a4SJacob Faibussowitsch case 4: 4575d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4576d71ae5a4SJacob Faibussowitsch break; 4577d71ae5a4SJacob Faibussowitsch default: 4578d71ae5a4SJacob Faibussowitsch break; 4579ba2698f1SMatthew G. Knepley } 4580ba2698f1SMatthew G. Knepley } 4581ba2698f1SMatthew G. Knepley } 4582412e9a14SMatthew G. Knepley *pt = ct; 45833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4584ba2698f1SMatthew G. Knepley } 4585412e9a14SMatthew G. Knepley 4586412e9a14SMatthew G. Knepley /*@ 4587412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4588412e9a14SMatthew G. Knepley 458920f4b53cSBarry Smith Collective 4590412e9a14SMatthew G. Knepley 4591412e9a14SMatthew G. Knepley Input Parameter: 459260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4593412e9a14SMatthew G. Knepley 4594412e9a14SMatthew G. Knepley Level: developer 4595412e9a14SMatthew G. Knepley 4596a1cb98faSBarry Smith Note: 4597a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4598a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4599a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4600412e9a14SMatthew G. Knepley 4601a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4602a1cb98faSBarry Smith 46031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4604412e9a14SMatthew G. Knepley @*/ 4605d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4606d71ae5a4SJacob Faibussowitsch { 4607412e9a14SMatthew G. Knepley DM_Plex *mesh; 4608412e9a14SMatthew G. Knepley DMLabel ctLabel; 4609412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4610412e9a14SMatthew G. Knepley 4611412e9a14SMatthew G. Knepley PetscFunctionBegin; 4612412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4613412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 46149566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 46159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 461721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 461821027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4619412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4620327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4621412e9a14SMatthew G. Knepley PetscInt pdepth; 4622412e9a14SMatthew G. Knepley 46239566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 46249566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4625476787b7SMatthew G. Knepley PetscCheck(ct != DM_POLYTOPE_UNKNOWN && ct != DM_POLYTOPE_UNKNOWN_CELL && ct != DM_POLYTOPE_UNKNOWN_FACE, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p); 46269566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 462721027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4628412e9a14SMatthew G. Knepley } 46299566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 46309566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 46313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4632ba2698f1SMatthew G. Knepley } 4633ba2698f1SMatthew G. Knepley 4634552f7358SJed Brown /*@C 4635552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4636552f7358SJed Brown 4637552f7358SJed Brown Not Collective 4638552f7358SJed Brown 4639552f7358SJed Brown Input Parameters: 4640a1cb98faSBarry Smith + dm - The `DMPLEX` object 4641552f7358SJed Brown . numPoints - The number of input points for the join 4642552f7358SJed Brown - points - The input points 4643552f7358SJed Brown 4644552f7358SJed Brown Output Parameters: 4645552f7358SJed Brown + numCoveredPoints - The number of points in the join 4646552f7358SJed Brown - coveredPoints - The points in the join 4647552f7358SJed Brown 4648552f7358SJed Brown Level: intermediate 4649552f7358SJed Brown 4650a1cb98faSBarry Smith Note: 4651a1cb98faSBarry Smith Currently, this is restricted to a single level join 4652552f7358SJed Brown 465360225df5SJacob Faibussowitsch Fortran Notes: 465420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46553813dfbdSMatthew G Knepley 46561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4657552f7358SJed Brown @*/ 4658d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4659d71ae5a4SJacob Faibussowitsch { 4660552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4661552f7358SJed Brown PetscInt *join[2]; 4662552f7358SJed Brown PetscInt joinSize, i = 0; 4663552f7358SJed Brown PetscInt dof, off, p, c, m; 46646302a7fbSVaclav Hapla PetscInt maxSupportSize; 4665552f7358SJed Brown 4666552f7358SJed Brown PetscFunctionBegin; 4667552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46684f572ea9SToby Isaac PetscAssertPointer(points, 3); 46694f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46704f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46716302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46726302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46736302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4674552f7358SJed Brown /* Copy in support of first point */ 46759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4677ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4678552f7358SJed Brown /* Check each successive support */ 4679552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4680552f7358SJed Brown PetscInt newJoinSize = 0; 4681552f7358SJed Brown 46829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4684552f7358SJed Brown for (c = 0; c < dof; ++c) { 4685552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4686552f7358SJed Brown 4687552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4688552f7358SJed Brown if (point == join[i][m]) { 4689552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4690552f7358SJed Brown break; 4691552f7358SJed Brown } 4692552f7358SJed Brown } 4693552f7358SJed Brown } 4694552f7358SJed Brown joinSize = newJoinSize; 4695552f7358SJed Brown i = 1 - i; 4696552f7358SJed Brown } 4697552f7358SJed Brown *numCoveredPoints = joinSize; 4698552f7358SJed Brown *coveredPoints = join[i]; 46996302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 47003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4701552f7358SJed Brown } 4702552f7358SJed Brown 4703552f7358SJed Brown /*@C 4704552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4705552f7358SJed Brown 4706552f7358SJed Brown Not Collective 4707552f7358SJed Brown 4708552f7358SJed Brown Input Parameters: 4709a1cb98faSBarry Smith + dm - The `DMPLEX` object 4710552f7358SJed Brown . numPoints - The number of input points for the join 4711552f7358SJed Brown - points - The input points 4712552f7358SJed Brown 4713552f7358SJed Brown Output Parameters: 4714552f7358SJed Brown + numCoveredPoints - The number of points in the join 4715552f7358SJed Brown - coveredPoints - The points in the join 4716552f7358SJed Brown 4717552f7358SJed Brown Level: intermediate 4718552f7358SJed Brown 471960225df5SJacob Faibussowitsch Fortran Notes: 472020f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4721a1cb98faSBarry Smith 47221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4723552f7358SJed Brown @*/ 4724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4725d71ae5a4SJacob Faibussowitsch { 4726552f7358SJed Brown PetscFunctionBegin; 4727552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47284f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 47294f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 47304f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4732d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 47333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4734552f7358SJed Brown } 4735552f7358SJed Brown 4736552f7358SJed Brown /*@C 4737552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4738552f7358SJed Brown 4739552f7358SJed Brown Not Collective 4740552f7358SJed Brown 4741552f7358SJed Brown Input Parameters: 4742a1cb98faSBarry Smith + dm - The `DMPLEX` object 4743552f7358SJed Brown . numPoints - The number of input points for the join 4744552f7358SJed Brown - points - The input points 4745552f7358SJed Brown 4746552f7358SJed Brown Output Parameters: 4747552f7358SJed Brown + numCoveredPoints - The number of points in the join 4748552f7358SJed Brown - coveredPoints - The points in the join 4749552f7358SJed Brown 4750552f7358SJed Brown Level: intermediate 4751552f7358SJed Brown 475260225df5SJacob Faibussowitsch Fortran Notes: 475320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4754a1cb98faSBarry Smith 47551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4756552f7358SJed Brown @*/ 4757d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4758d71ae5a4SJacob Faibussowitsch { 4759552f7358SJed Brown PetscInt *offsets, **closures; 4760552f7358SJed Brown PetscInt *join[2]; 4761552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 476224c766afSToby Isaac PetscInt p, d, c, m, ms; 4763552f7358SJed Brown 4764552f7358SJed Brown PetscFunctionBegin; 4765552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47664f572ea9SToby Isaac PetscAssertPointer(points, 3); 47674f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47684f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4769552f7358SJed Brown 47709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47729566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47736302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 477424c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47769566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4777552f7358SJed Brown 4778552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4779552f7358SJed Brown PetscInt closureSize; 4780552f7358SJed Brown 47819566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47820d644c17SKarl Rupp 4783552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4784552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4785552f7358SJed Brown PetscInt pStart, pEnd, i; 4786552f7358SJed Brown 47879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4788552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4789552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4790552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4791552f7358SJed Brown break; 4792552f7358SJed Brown } 4793552f7358SJed Brown } 4794552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4795552f7358SJed Brown } 479663a3b9bcSJacob Faibussowitsch PetscCheck(offsets[p * (depth + 2) + depth + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (depth + 2) + depth + 1], closureSize); 4797552f7358SJed Brown } 4798552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4799552f7358SJed Brown PetscInt dof; 4800552f7358SJed Brown 4801552f7358SJed Brown /* Copy in support of first point */ 4802552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4803ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4804552f7358SJed Brown /* Check each successive cone */ 4805552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4806552f7358SJed Brown PetscInt newJoinSize = 0; 4807552f7358SJed Brown 4808552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4809552f7358SJed Brown for (c = 0; c < dof; ++c) { 4810552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4811552f7358SJed Brown 4812552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4813552f7358SJed Brown if (point == join[i][m]) { 4814552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4815552f7358SJed Brown break; 4816552f7358SJed Brown } 4817552f7358SJed Brown } 4818552f7358SJed Brown } 4819552f7358SJed Brown joinSize = newJoinSize; 4820552f7358SJed Brown i = 1 - i; 4821552f7358SJed Brown } 4822552f7358SJed Brown if (joinSize) break; 4823552f7358SJed Brown } 4824552f7358SJed Brown *numCoveredPoints = joinSize; 4825552f7358SJed Brown *coveredPoints = join[i]; 482648a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 48279566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 48289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48296302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 48303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4831552f7358SJed Brown } 4832552f7358SJed Brown 4833552f7358SJed Brown /*@C 4834552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4835552f7358SJed Brown 4836552f7358SJed Brown Not Collective 4837552f7358SJed Brown 4838552f7358SJed Brown Input Parameters: 4839a1cb98faSBarry Smith + dm - The `DMPLEX` object 4840552f7358SJed Brown . numPoints - The number of input points for the meet 4841552f7358SJed Brown - points - The input points 4842552f7358SJed Brown 4843552f7358SJed Brown Output Parameters: 484460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 484560225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4846552f7358SJed Brown 4847552f7358SJed Brown Level: intermediate 4848552f7358SJed Brown 4849a1cb98faSBarry Smith Note: 4850a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4851552f7358SJed Brown 48523813dfbdSMatthew G Knepley Fortran Notes: 485320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48543813dfbdSMatthew G Knepley 48551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4856552f7358SJed Brown @*/ 4857d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4858d71ae5a4SJacob Faibussowitsch { 4859552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4860552f7358SJed Brown PetscInt *meet[2]; 4861552f7358SJed Brown PetscInt meetSize, i = 0; 4862552f7358SJed Brown PetscInt dof, off, p, c, m; 48636302a7fbSVaclav Hapla PetscInt maxConeSize; 4864552f7358SJed Brown 4865552f7358SJed Brown PetscFunctionBegin; 4866552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48674f572ea9SToby Isaac PetscAssertPointer(points, 3); 48684f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48694f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48706302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48716302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48726302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4873552f7358SJed Brown /* Copy in cone of first point */ 48749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4876ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4877552f7358SJed Brown /* Check each successive cone */ 4878552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4879552f7358SJed Brown PetscInt newMeetSize = 0; 4880552f7358SJed Brown 48819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4883552f7358SJed Brown for (c = 0; c < dof; ++c) { 4884552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4885552f7358SJed Brown 4886552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4887552f7358SJed Brown if (point == meet[i][m]) { 4888552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4889552f7358SJed Brown break; 4890552f7358SJed Brown } 4891552f7358SJed Brown } 4892552f7358SJed Brown } 4893552f7358SJed Brown meetSize = newMeetSize; 4894552f7358SJed Brown i = 1 - i; 4895552f7358SJed Brown } 4896552f7358SJed Brown *numCoveringPoints = meetSize; 4897552f7358SJed Brown *coveringPoints = meet[i]; 48986302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4900552f7358SJed Brown } 4901552f7358SJed Brown 4902552f7358SJed Brown /*@C 4903552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4904552f7358SJed Brown 4905552f7358SJed Brown Not Collective 4906552f7358SJed Brown 4907552f7358SJed Brown Input Parameters: 4908a1cb98faSBarry Smith + dm - The `DMPLEX` object 4909552f7358SJed Brown . numPoints - The number of input points for the meet 4910552f7358SJed Brown - points - The input points 4911552f7358SJed Brown 4912552f7358SJed Brown Output Parameters: 4913552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4914552f7358SJed Brown - coveredPoints - The points in the meet 4915552f7358SJed Brown 4916552f7358SJed Brown Level: intermediate 4917552f7358SJed Brown 491860225df5SJacob Faibussowitsch Fortran Notes: 491920f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49203813dfbdSMatthew G Knepley 49211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4922552f7358SJed Brown @*/ 4923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4924d71ae5a4SJacob Faibussowitsch { 4925552f7358SJed Brown PetscFunctionBegin; 4926552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49274f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49284f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49294f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4931d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4933552f7358SJed Brown } 4934552f7358SJed Brown 4935552f7358SJed Brown /*@C 4936552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4937552f7358SJed Brown 4938552f7358SJed Brown Not Collective 4939552f7358SJed Brown 4940552f7358SJed Brown Input Parameters: 4941a1cb98faSBarry Smith + dm - The `DMPLEX` object 4942552f7358SJed Brown . numPoints - The number of input points for the meet 4943552f7358SJed Brown - points - The input points 4944552f7358SJed Brown 4945552f7358SJed Brown Output Parameters: 4946552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4947552f7358SJed Brown - coveredPoints - The points in the meet 4948552f7358SJed Brown 4949552f7358SJed Brown Level: intermediate 4950552f7358SJed Brown 495160225df5SJacob Faibussowitsch Fortran Notes: 495220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49533813dfbdSMatthew G Knepley 49541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4955552f7358SJed Brown @*/ 4956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4957d71ae5a4SJacob Faibussowitsch { 4958552f7358SJed Brown PetscInt *offsets, **closures; 4959552f7358SJed Brown PetscInt *meet[2]; 4960552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 496124c766afSToby Isaac PetscInt p, h, c, m, mc; 4962552f7358SJed Brown 4963552f7358SJed Brown PetscFunctionBegin; 4964552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49654f572ea9SToby Isaac PetscAssertPointer(points, 3); 49664f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49674f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4968552f7358SJed Brown 49699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49726302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 497324c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4976552f7358SJed Brown 4977552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4978552f7358SJed Brown PetscInt closureSize; 4979552f7358SJed Brown 49809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49810d644c17SKarl Rupp 4982552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4983552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4984552f7358SJed Brown PetscInt pStart, pEnd, i; 4985552f7358SJed Brown 49869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4987552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4988552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4989552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4990552f7358SJed Brown break; 4991552f7358SJed Brown } 4992552f7358SJed Brown } 4993552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4994552f7358SJed Brown } 499563a3b9bcSJacob Faibussowitsch PetscCheck(offsets[p * (height + 2) + height + 1] == closureSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p * (height + 2) + height + 1], closureSize); 4996552f7358SJed Brown } 4997552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4998552f7358SJed Brown PetscInt dof; 4999552f7358SJed Brown 5000552f7358SJed Brown /* Copy in cone of first point */ 5001552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5002ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5003552f7358SJed Brown /* Check each successive cone */ 5004552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5005552f7358SJed Brown PetscInt newMeetSize = 0; 5006552f7358SJed Brown 5007552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5008552f7358SJed Brown for (c = 0; c < dof; ++c) { 5009552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5010552f7358SJed Brown 5011552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5012552f7358SJed Brown if (point == meet[i][m]) { 5013552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5014552f7358SJed Brown break; 5015552f7358SJed Brown } 5016552f7358SJed Brown } 5017552f7358SJed Brown } 5018552f7358SJed Brown meetSize = newMeetSize; 5019552f7358SJed Brown i = 1 - i; 5020552f7358SJed Brown } 5021552f7358SJed Brown if (meetSize) break; 5022552f7358SJed Brown } 5023552f7358SJed Brown *numCoveredPoints = meetSize; 5024552f7358SJed Brown *coveredPoints = meet[i]; 502548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 50269566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50286302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 50293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5030552f7358SJed Brown } 5031552f7358SJed Brown 50324e3744c5SMatthew G. Knepley /*@C 5033a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50344e3744c5SMatthew G. Knepley 50354e3744c5SMatthew G. Knepley Not Collective 50364e3744c5SMatthew G. Knepley 50374e3744c5SMatthew G. Knepley Input Parameters: 5038a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5039a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50404e3744c5SMatthew G. Knepley 50412fe279fdSBarry Smith Output Parameter: 5042a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50434e3744c5SMatthew G. Knepley 50444e3744c5SMatthew G. Knepley Level: intermediate 50454e3744c5SMatthew G. Knepley 5046a1cb98faSBarry Smith Note: 50473c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50484e3744c5SMatthew G. Knepley 50491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50504e3744c5SMatthew G. Knepley @*/ 5051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5052d71ae5a4SJacob Faibussowitsch { 50534e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50544e3744c5SMatthew G. Knepley 50554e3744c5SMatthew G. Knepley PetscFunctionBegin; 50564e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50574e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50584f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50594e3744c5SMatthew G. Knepley 50604e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50633ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50659566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50663ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50674e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50684e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50694e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50704e3744c5SMatthew G. Knepley 50719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50749566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50773ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50784e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50793ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50803ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50814e3744c5SMatthew G. Knepley } 50829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50859566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50863ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50874e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50883ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50894e3744c5SMatthew G. Knepley } 50904e3744c5SMatthew G. Knepley } 50914e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50934e3744c5SMatthew G. Knepley } 50944e3744c5SMatthew G. Knepley 50957cd05799SMatthew G. Knepley /*@C 50967cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50977cd05799SMatthew G. Knepley 50987cd05799SMatthew G. Knepley Not Collective 50997cd05799SMatthew G. Knepley 51007cd05799SMatthew G. Knepley Input Parameters: 5101a1cb98faSBarry Smith + dm - The `DMPLEX` 51027cd05799SMatthew G. Knepley . cellDim - The cell dimension 51037cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 51047cd05799SMatthew G. Knepley 51052fe279fdSBarry Smith Output Parameter: 51067cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 51077cd05799SMatthew G. Knepley 51087cd05799SMatthew G. Knepley Level: developer 51097cd05799SMatthew G. Knepley 5110a1cb98faSBarry Smith Note: 51117cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 51127cd05799SMatthew G. Knepley 51131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51147cd05799SMatthew G. Knepley @*/ 5115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5116d71ae5a4SJacob Faibussowitsch { 511782f516ccSBarry Smith MPI_Comm comm; 5118552f7358SJed Brown 5119552f7358SJed Brown PetscFunctionBegin; 51209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 51214f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5122552f7358SJed Brown switch (cellDim) { 5123d71ae5a4SJacob Faibussowitsch case 0: 5124d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5125d71ae5a4SJacob Faibussowitsch break; 5126d71ae5a4SJacob Faibussowitsch case 1: 5127d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5128d71ae5a4SJacob Faibussowitsch break; 5129552f7358SJed Brown case 2: 5130552f7358SJed Brown switch (numCorners) { 513119436ca2SJed Brown case 3: /* triangle */ 513219436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5133552f7358SJed Brown break; 513419436ca2SJed Brown case 4: /* quadrilateral */ 513519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5136552f7358SJed Brown break; 513719436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 513819436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5139552f7358SJed Brown break; 514019436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 514119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5142552f7358SJed Brown break; 5143d71ae5a4SJacob Faibussowitsch default: 5144d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5145552f7358SJed Brown } 5146552f7358SJed Brown break; 5147552f7358SJed Brown case 3: 5148552f7358SJed Brown switch (numCorners) { 514919436ca2SJed Brown case 4: /* tetradehdron */ 515019436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5151552f7358SJed Brown break; 515219436ca2SJed Brown case 6: /* tet cohesive cells */ 515319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5154552f7358SJed Brown break; 515519436ca2SJed Brown case 8: /* hexahedron */ 515619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5157552f7358SJed Brown break; 515819436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 515919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5160552f7358SJed Brown break; 516119436ca2SJed Brown case 10: /* quadratic tetrahedron */ 516219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5163552f7358SJed Brown break; 516419436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 516519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5166552f7358SJed Brown break; 516719436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 516819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5169552f7358SJed Brown break; 517019436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 517119436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5172552f7358SJed Brown break; 5173d71ae5a4SJacob Faibussowitsch default: 5174d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5175552f7358SJed Brown } 5176552f7358SJed Brown break; 5177d71ae5a4SJacob Faibussowitsch default: 5178d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5179552f7358SJed Brown } 51803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5181552f7358SJed Brown } 5182552f7358SJed Brown 5183552f7358SJed Brown /*@ 5184a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5185552f7358SJed Brown 5186552f7358SJed Brown Not Collective 5187552f7358SJed Brown 5188aa50250dSMatthew G. Knepley Input Parameter: 5189a1cb98faSBarry Smith . dm - The `DMPLEX` object 5190552f7358SJed Brown 5191aa50250dSMatthew G. Knepley Output Parameter: 5192a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5193552f7358SJed Brown 5194552f7358SJed Brown Level: developer 5195552f7358SJed Brown 51961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5197aa50250dSMatthew G. Knepley @*/ 5198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5199d71ae5a4SJacob Faibussowitsch { 5200aa50250dSMatthew G. Knepley PetscFunctionBegin; 5201aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52024f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5203c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 52043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5205aa50250dSMatthew G. Knepley } 5206aa50250dSMatthew G. Knepley 5207aa50250dSMatthew G. Knepley /*@ 5208aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5209aa50250dSMatthew G. Knepley 5210aa50250dSMatthew G. Knepley Not Collective 5211aa50250dSMatthew G. Knepley 5212aa50250dSMatthew G. Knepley Input Parameter: 5213a1cb98faSBarry Smith . dm - The `DMPLEX` object 5214aa50250dSMatthew G. Knepley 5215aa50250dSMatthew G. Knepley Output Parameter: 5216aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5217aa50250dSMatthew G. Knepley 5218aa50250dSMatthew G. Knepley Level: developer 5219552f7358SJed Brown 5220b1bb481bSMatthew Knepley Notes: 5221a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5222a1cb98faSBarry Smith 5223a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5224a1cb98faSBarry Smith 5225dc287ab2SVaclav Hapla An empty mesh gives -1. 5226b1bb481bSMatthew Knepley 52271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5228552f7358SJed Brown @*/ 5229d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5230d71ae5a4SJacob Faibussowitsch { 52319f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5232aa50250dSMatthew G. Knepley DMLabel label; 5233aa50250dSMatthew G. Knepley PetscInt d = 0; 5234552f7358SJed Brown 5235552f7358SJed Brown PetscFunctionBegin; 5236552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52374f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52389f4ada15SMatthew G. Knepley if (mesh->tr) { 52399f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52409f4ada15SMatthew G. Knepley } else { 52419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52429566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5243552f7358SJed Brown *depth = d - 1; 52449f4ada15SMatthew G. Knepley } 52453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5246552f7358SJed Brown } 5247552f7358SJed Brown 5248552f7358SJed Brown /*@ 524920f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5250552f7358SJed Brown 5251552f7358SJed Brown Not Collective 5252552f7358SJed Brown 5253552f7358SJed Brown Input Parameters: 5254a1cb98faSBarry Smith + dm - The `DMPLEX` object 5255570fa34dSVaclav Hapla - depth - The requested depth 5256552f7358SJed Brown 5257552f7358SJed Brown Output Parameters: 525820f4b53cSBarry Smith + start - The first point at this `depth` 525920f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5260552f7358SJed Brown 5261552f7358SJed Brown Level: developer 5262552f7358SJed Brown 5263a1cb98faSBarry Smith Notes: 5264a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5265a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5266a1cb98faSBarry Smith higher dimension, e.g., "edges". 5267a1cb98faSBarry Smith 52682827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5269552f7358SJed Brown @*/ 5270d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5271d71ae5a4SJacob Faibussowitsch { 52729f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5273aa50250dSMatthew G. Knepley DMLabel label; 527463d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5275552f7358SJed Brown 5276552f7358SJed Brown PetscFunctionBegin; 5277552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52789371c9d4SSatish Balay if (start) { 52794f572ea9SToby Isaac PetscAssertPointer(start, 3); 52809371c9d4SSatish Balay *start = 0; 52819371c9d4SSatish Balay } 52829371c9d4SSatish Balay if (end) { 52834f572ea9SToby Isaac PetscAssertPointer(end, 4); 52849371c9d4SSatish Balay *end = 0; 52859371c9d4SSatish Balay } 52869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52873ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5288570fa34dSVaclav Hapla if (depth < 0) { 528963d1a920SMatthew G. Knepley if (start) *start = pStart; 529063d1a920SMatthew G. Knepley if (end) *end = pEnd; 52913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5292552f7358SJed Brown } 52939f4ada15SMatthew G. Knepley if (mesh->tr) { 52949f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52959f4ada15SMatthew G. Knepley } else { 52969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 529728b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5298570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52999f4ada15SMatthew G. Knepley } 53003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5301552f7358SJed Brown } 5302552f7358SJed Brown 5303552f7358SJed Brown /*@ 530420f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5305552f7358SJed Brown 5306552f7358SJed Brown Not Collective 5307552f7358SJed Brown 5308552f7358SJed Brown Input Parameters: 5309a1cb98faSBarry Smith + dm - The `DMPLEX` object 5310570fa34dSVaclav Hapla - height - The requested height 5311552f7358SJed Brown 5312552f7358SJed Brown Output Parameters: 531320f4b53cSBarry Smith + start - The first point at this `height` 531420f4b53cSBarry Smith - end - One beyond the last point at this `height` 5315552f7358SJed Brown 5316552f7358SJed Brown Level: developer 5317552f7358SJed Brown 5318a1cb98faSBarry Smith Notes: 5319a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5320a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5321a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5322a1cb98faSBarry Smith 53232827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5324552f7358SJed Brown @*/ 5325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5326d71ae5a4SJacob Faibussowitsch { 5327aa50250dSMatthew G. Knepley DMLabel label; 532863d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5329552f7358SJed Brown 5330552f7358SJed Brown PetscFunctionBegin; 5331552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53329371c9d4SSatish Balay if (start) { 53334f572ea9SToby Isaac PetscAssertPointer(start, 3); 53349371c9d4SSatish Balay *start = 0; 53359371c9d4SSatish Balay } 53369371c9d4SSatish Balay if (end) { 53374f572ea9SToby Isaac PetscAssertPointer(end, 4); 53389371c9d4SSatish Balay *end = 0; 53399371c9d4SSatish Balay } 53409566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53413ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5342570fa34dSVaclav Hapla if (height < 0) { 534363d1a920SMatthew G. Knepley if (start) *start = pStart; 534463d1a920SMatthew G. Knepley if (end) *end = pEnd; 53453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5346552f7358SJed Brown } 53479566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 534859e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 534959e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 535059e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 535159e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5353552f7358SJed Brown } 5354552f7358SJed Brown 5355ba2698f1SMatthew G. Knepley /*@ 535620f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5357ba2698f1SMatthew G. Knepley 5358ba2698f1SMatthew G. Knepley Not Collective 5359ba2698f1SMatthew G. Knepley 5360d8d19677SJose E. Roman Input Parameters: 5361a1cb98faSBarry Smith + dm - The `DMPLEX` object 5362ba2698f1SMatthew G. Knepley - point - The point 5363ba2698f1SMatthew G. Knepley 5364ba2698f1SMatthew G. Knepley Output Parameter: 536520f4b53cSBarry Smith . depth - The depth of the `point` 5366ba2698f1SMatthew G. Knepley 5367ba2698f1SMatthew G. Knepley Level: intermediate 5368ba2698f1SMatthew G. Knepley 53691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5370ba2698f1SMatthew G. Knepley @*/ 5371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5372d71ae5a4SJacob Faibussowitsch { 5373ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5374ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53754f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53769566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5378ba2698f1SMatthew G. Knepley } 5379ba2698f1SMatthew G. Knepley 5380ba2698f1SMatthew G. Knepley /*@ 538120f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53820c0a32dcSVaclav Hapla 53830c0a32dcSVaclav Hapla Not Collective 53840c0a32dcSVaclav Hapla 5385d8d19677SJose E. Roman Input Parameters: 5386a1cb98faSBarry Smith + dm - The `DMPLEX` object 53870c0a32dcSVaclav Hapla - point - The point 53880c0a32dcSVaclav Hapla 53890c0a32dcSVaclav Hapla Output Parameter: 539020f4b53cSBarry Smith . height - The height of the `point` 53910c0a32dcSVaclav Hapla 53920c0a32dcSVaclav Hapla Level: intermediate 53930c0a32dcSVaclav Hapla 53941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53950c0a32dcSVaclav Hapla @*/ 5396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5397d71ae5a4SJacob Faibussowitsch { 53980c0a32dcSVaclav Hapla PetscInt n, pDepth; 53990c0a32dcSVaclav Hapla 54000c0a32dcSVaclav Hapla PetscFunctionBegin; 54010c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54024f572ea9SToby Isaac PetscAssertPointer(height, 3); 54039566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 54049566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 54050c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 54063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54070c0a32dcSVaclav Hapla } 54080c0a32dcSVaclav Hapla 54090c0a32dcSVaclav Hapla /*@ 5410a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5411ba2698f1SMatthew G. Knepley 5412ba2698f1SMatthew G. Knepley Not Collective 5413ba2698f1SMatthew G. Knepley 5414ba2698f1SMatthew G. Knepley Input Parameter: 5415a1cb98faSBarry Smith . dm - The `DMPLEX` object 5416ba2698f1SMatthew G. Knepley 5417ba2698f1SMatthew G. Knepley Output Parameter: 5418a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5419412e9a14SMatthew G. Knepley 5420ba2698f1SMatthew G. Knepley Level: developer 5421ba2698f1SMatthew G. Knepley 5422a1cb98faSBarry Smith Note: 5423a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5424a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5425a1cb98faSBarry Smith 54261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5427ba2698f1SMatthew G. Knepley @*/ 5428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5429d71ae5a4SJacob Faibussowitsch { 5430ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5431ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54324f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 54339566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5434ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5436ba2698f1SMatthew G. Knepley } 5437ba2698f1SMatthew G. Knepley 5438ba2698f1SMatthew G. Knepley /*@ 5439ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5440ba2698f1SMatthew G. Knepley 5441ba2698f1SMatthew G. Knepley Not Collective 5442ba2698f1SMatthew G. Knepley 5443d8d19677SJose E. Roman Input Parameters: 5444a1cb98faSBarry Smith + dm - The `DMPLEX` object 5445ba2698f1SMatthew G. Knepley - cell - The cell 5446ba2698f1SMatthew G. Knepley 5447ba2698f1SMatthew G. Knepley Output Parameter: 5448ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5449ba2698f1SMatthew G. Knepley 5450ba2698f1SMatthew G. Knepley Level: intermediate 5451ba2698f1SMatthew G. Knepley 54521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5453ba2698f1SMatthew G. Knepley @*/ 5454d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5455d71ae5a4SJacob Faibussowitsch { 54569f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5457ba2698f1SMatthew G. Knepley DMLabel label; 5458ba2698f1SMatthew G. Knepley PetscInt ct; 5459ba2698f1SMatthew G. Knepley 5460ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5461ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54624f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54639f4ada15SMatthew G. Knepley if (mesh->tr) { 54649f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54659f4ada15SMatthew G. Knepley } else { 546621027e53SStefano Zampini PetscInt pStart, pEnd; 546721027e53SStefano Zampini 546821027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 546921027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 547021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 547121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 547221027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 547321027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 547421027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 547521027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 547621027e53SStefano Zampini } 547721027e53SStefano Zampini } 547821027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 547921027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54819566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 548263a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5483936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 548421027e53SStefano Zampini } 54859f4ada15SMatthew G. Knepley } 54863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5487ba2698f1SMatthew G. Knepley } 5488ba2698f1SMatthew G. Knepley 5489412e9a14SMatthew G. Knepley /*@ 5490412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5491412e9a14SMatthew G. Knepley 5492412e9a14SMatthew G. Knepley Not Collective 5493412e9a14SMatthew G. Knepley 5494412e9a14SMatthew G. Knepley Input Parameters: 5495a1cb98faSBarry Smith + dm - The `DMPLEX` object 5496412e9a14SMatthew G. Knepley . cell - The cell 5497412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5498412e9a14SMatthew G. Knepley 5499a1cb98faSBarry Smith Level: advanced 5500a1cb98faSBarry Smith 5501a1cb98faSBarry Smith Note: 5502a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5503412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5504412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5505db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5506412e9a14SMatthew G. Knepley 55071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5508412e9a14SMatthew G. Knepley @*/ 5509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5510d71ae5a4SJacob Faibussowitsch { 551121027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5512412e9a14SMatthew G. Knepley DMLabel label; 551321027e53SStefano Zampini PetscInt pStart, pEnd; 5514412e9a14SMatthew G. Knepley 5515412e9a14SMatthew G. Knepley PetscFunctionBegin; 5516412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 551721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 55189566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 55199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 552021027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 552121027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 55223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5523412e9a14SMatthew G. Knepley } 5524412e9a14SMatthew G. Knepley 5525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5526d71ae5a4SJacob Faibussowitsch { 5527efe440bfSMatthew G. Knepley PetscSection section, s; 5528efe440bfSMatthew G. Knepley Mat m; 55293e922f36SToby Isaac PetscInt maxHeight; 5530dd4c3f67SMatthew G. Knepley const char *prefix; 5531552f7358SJed Brown 5532552f7358SJed Brown PetscFunctionBegin; 55339566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5534dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5535dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5536dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55379566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55389566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55399566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55409566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55419566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 55439566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 55449566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 55459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 55469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 55478f4c458bSMatthew G. Knepley 55489566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55499566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5550dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5551dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5553552f7358SJed Brown } 5554552f7358SJed Brown 5555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5556d71ae5a4SJacob Faibussowitsch { 55576858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55586858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5559f19dbd58SToby Isaac 5560f19dbd58SToby Isaac PetscFunctionBegin; 5561f19dbd58SToby Isaac *field = NULL; 55629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55646858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5566f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55676858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55686858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5569f19dbd58SToby Isaac } 55703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5571f19dbd58SToby Isaac } 5572f19dbd58SToby Isaac 55737cd05799SMatthew G. Knepley /*@C 55747cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55757cd05799SMatthew G. Knepley 55767cd05799SMatthew G. Knepley Not Collective 55777cd05799SMatthew G. Knepley 55782fe279fdSBarry Smith Input Parameter: 5579a1cb98faSBarry Smith . dm - The `DMPLEX` object 55807cd05799SMatthew G. Knepley 55817cd05799SMatthew G. Knepley Output Parameter: 5582a1cb98faSBarry Smith . section - The `PetscSection` object 55837cd05799SMatthew G. Knepley 55847cd05799SMatthew G. Knepley Level: developer 55857cd05799SMatthew G. Knepley 55861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55877cd05799SMatthew G. Knepley @*/ 5588d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5589d71ae5a4SJacob Faibussowitsch { 5590552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5591552f7358SJed Brown 5592552f7358SJed Brown PetscFunctionBegin; 5593552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5594552f7358SJed Brown if (section) *section = mesh->coneSection; 55953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5596552f7358SJed Brown } 5597552f7358SJed Brown 55987cd05799SMatthew G. Knepley /*@C 55997cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 56007cd05799SMatthew G. Knepley 56017cd05799SMatthew G. Knepley Not Collective 56027cd05799SMatthew G. Knepley 56032fe279fdSBarry Smith Input Parameter: 5604a1cb98faSBarry Smith . dm - The `DMPLEX` object 56057cd05799SMatthew G. Knepley 56067cd05799SMatthew G. Knepley Output Parameter: 5607a1cb98faSBarry Smith . section - The `PetscSection` object 56087cd05799SMatthew G. Knepley 56097cd05799SMatthew G. Knepley Level: developer 56107cd05799SMatthew G. Knepley 56111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 56127cd05799SMatthew G. Knepley @*/ 5613d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5614d71ae5a4SJacob Faibussowitsch { 56158cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 56168cb4d582SMatthew G. Knepley 56178cb4d582SMatthew G. Knepley PetscFunctionBegin; 56188cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56198cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 56203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56218cb4d582SMatthew G. Knepley } 56228cb4d582SMatthew G. Knepley 56237cd05799SMatthew G. Knepley /*@C 56247cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 56257cd05799SMatthew G. Knepley 56267cd05799SMatthew G. Knepley Not Collective 56277cd05799SMatthew G. Knepley 56282fe279fdSBarry Smith Input Parameter: 5629a1cb98faSBarry Smith . dm - The `DMPLEX` object 56307cd05799SMatthew G. Knepley 56317cd05799SMatthew G. Knepley Output Parameter: 56327cd05799SMatthew G. Knepley . cones - The cone for each point 56337cd05799SMatthew G. Knepley 56347cd05799SMatthew G. Knepley Level: developer 56357cd05799SMatthew G. Knepley 56361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56377cd05799SMatthew G. Knepley @*/ 5638d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5639d71ae5a4SJacob Faibussowitsch { 5640552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5641552f7358SJed Brown 5642552f7358SJed Brown PetscFunctionBegin; 5643552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5644552f7358SJed Brown if (cones) *cones = mesh->cones; 56453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5646552f7358SJed Brown } 5647552f7358SJed Brown 56487cd05799SMatthew G. Knepley /*@C 56497cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56507cd05799SMatthew G. Knepley 56517cd05799SMatthew G. Knepley Not Collective 56527cd05799SMatthew G. Knepley 56532fe279fdSBarry Smith Input Parameter: 5654a1cb98faSBarry Smith . dm - The `DMPLEX` object 56557cd05799SMatthew G. Knepley 56567cd05799SMatthew G. Knepley Output Parameter: 5657b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56587cd05799SMatthew G. Knepley 56597cd05799SMatthew G. Knepley Level: developer 56607cd05799SMatthew G. Knepley 5661b5a892a1SMatthew G. Knepley Notes: 5662a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5663b5a892a1SMatthew G. Knepley 5664a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5665b5a892a1SMatthew G. Knepley 56661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56677cd05799SMatthew G. Knepley @*/ 5668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5669d71ae5a4SJacob Faibussowitsch { 5670552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5671552f7358SJed Brown 5672552f7358SJed Brown PetscFunctionBegin; 5673552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5674552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5676552f7358SJed Brown } 5677552f7358SJed Brown 5678552f7358SJed Brown /******************************** FEM Support **********************************/ 5679552f7358SJed Brown 5680d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5681d2b2dc1eSMatthew G. Knepley { 5682d2b2dc1eSMatthew G. Knepley PetscInt depth; 5683d2b2dc1eSMatthew G. Knepley 5684d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5685d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5686d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5687d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5688d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5689d2b2dc1eSMatthew G. Knepley } 5690d2b2dc1eSMatthew G. Knepley 56915962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56925962854dSMatthew G. Knepley { 56935962854dSMatthew G. Knepley PetscInt depth; 56945962854dSMatthew G. Knepley 56955962854dSMatthew G. Knepley PetscFunctionBegin; 56965962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56975962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56985962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56995962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57005962854dSMatthew G. Knepley } 57015962854dSMatthew G. Knepley 57029e8305c2SJed Brown /* 57039e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 57049e8305c2SJed Brown representing a line in the section. 57059e8305c2SJed Brown */ 57065f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5707d71ae5a4SJacob Faibussowitsch { 5708e327e467SRezgar Shakeri PetscObject obj; 5709e327e467SRezgar Shakeri PetscClassId id; 5710e327e467SRezgar Shakeri PetscFE fe = NULL; 5711e327e467SRezgar Shakeri 57129e8305c2SJed Brown PetscFunctionBeginHot; 57139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5714e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5715e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5716e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5717e327e467SRezgar Shakeri 5718e327e467SRezgar Shakeri if (!fe) { 5719e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 57209e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 57219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 57229e8305c2SJed Brown *k = *k / *Nc + 1; 5723e327e467SRezgar Shakeri } else { 5724e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 57255f82726aSMatthew G. Knepley PetscDualSpace dsp; 57265f82726aSMatthew G. Knepley 5727e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 57285f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 57295f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5730e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 57315f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 57325f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 57335f82726aSMatthew G. Knepley } 57345f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57355f82726aSMatthew G. Knepley } 57365f82726aSMatthew G. Knepley 57375f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 57385f82726aSMatthew G. Knepley { 57395f82726aSMatthew G. Knepley PetscFunctionBeginHot; 57405f82726aSMatthew G. Knepley if (tensor) { 57415f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 57425f82726aSMatthew G. Knepley } else { 57435f82726aSMatthew G. Knepley switch (dim) { 57445f82726aSMatthew G. Knepley case 1: 57455f82726aSMatthew G. Knepley *dof = k + 1; 57465f82726aSMatthew G. Knepley break; 57475f82726aSMatthew G. Knepley case 2: 57485f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 57495f82726aSMatthew G. Knepley break; 57505f82726aSMatthew G. Knepley case 3: 57515f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 57525f82726aSMatthew G. Knepley break; 57535f82726aSMatthew G. Knepley default: 57545f82726aSMatthew G. Knepley *dof = 0; 57555f82726aSMatthew G. Knepley } 57569e8305c2SJed Brown } 57573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57589e8305c2SJed Brown } 57599e8305c2SJed Brown 5760a4355906SMatthew Knepley /*@ 5761bc1eb3faSJed Brown 5762bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5763bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 576420f4b53cSBarry Smith section provided (or the section of the `DM`). 5765a4355906SMatthew Knepley 5766a4355906SMatthew Knepley Input Parameters: 576720f4b53cSBarry Smith + dm - The `DM` 576820f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 576920f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5770a4355906SMatthew Knepley 5771bc1eb3faSJed Brown Example: 5772bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5773bc1eb3faSJed Brown .vb 5774bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5775bc1eb3faSJed Brown 5776bc1eb3faSJed Brown v4 -- e6 -- v3 5777bc1eb3faSJed Brown | | 5778bc1eb3faSJed Brown e7 c0 e8 5779bc1eb3faSJed Brown | | 5780bc1eb3faSJed Brown v1 -- e5 -- v2 5781bc1eb3faSJed Brown .ve 5782bc1eb3faSJed Brown 5783bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5784bc1eb3faSJed Brown dofs in the order of points, e.g., 5785bc1eb3faSJed Brown .vb 5786bc1eb3faSJed Brown c0 -> [0,1,2,3] 5787bc1eb3faSJed Brown v1 -> [4] 5788bc1eb3faSJed Brown ... 5789bc1eb3faSJed Brown e5 -> [8, 9] 5790bc1eb3faSJed Brown .ve 5791bc1eb3faSJed Brown 5792bc1eb3faSJed Brown which corresponds to the dofs 5793bc1eb3faSJed Brown .vb 5794bc1eb3faSJed Brown 6 10 11 7 5795bc1eb3faSJed Brown 13 2 3 15 5796bc1eb3faSJed Brown 12 0 1 14 5797bc1eb3faSJed Brown 4 8 9 5 5798bc1eb3faSJed Brown .ve 5799bc1eb3faSJed Brown 5800bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5801bc1eb3faSJed Brown .vb 5802bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5803bc1eb3faSJed Brown .ve 5804bc1eb3faSJed Brown 5805bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5806bc1eb3faSJed Brown .vb 5807bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5808bc1eb3faSJed Brown .ve 5809bc1eb3faSJed Brown 5810a4355906SMatthew Knepley Level: developer 5811a4355906SMatthew Knepley 5812da9ac489SAlbert Cowie Notes: 5813a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5814a1cb98faSBarry Smith degree of the basis. 5815a1cb98faSBarry Smith 5816da9ac489SAlbert Cowie This is required to run with libCEED. 5817da9ac489SAlbert Cowie 58181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5819a4355906SMatthew Knepley @*/ 5820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5821d71ae5a4SJacob Faibussowitsch { 58227391a63aSMatthew G. Knepley DMLabel label; 5823bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 58245f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 58253194fc30SMatthew G. Knepley 58263194fc30SMatthew G. Knepley PetscFunctionBegin; 58279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 58283ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5829a433471fSStefano Zampini if (point < 0) { 5830a433471fSStefano Zampini PetscInt sStart, sEnd; 5831a433471fSStefano Zampini 58329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5833a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5834a433471fSStefano Zampini } 58359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 58369566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 58379566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58389371c9d4SSatish Balay if (depth == 1) { 58399371c9d4SSatish Balay eStart = point; 58409371c9d4SSatish Balay } else if (depth == dim) { 58417391a63aSMatthew G. Knepley const PetscInt *cone; 58427391a63aSMatthew G. Knepley 58439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5844d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5845d4e6627bSStefano Zampini else if (dim == 3) { 5846d4e6627bSStefano Zampini const PetscInt *cone2; 58479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5848d4e6627bSStefano Zampini eStart = cone2[0]; 584963a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim); 585063a3b9bcSJacob Faibussowitsch } else PetscCheck(depth < 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim); 5851e327e467SRezgar Shakeri 58529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5853bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5854bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5855bb197d40SJed Brown PetscInt *perm; 5856bb197d40SJed Brown 58573194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 58585f82726aSMatthew G. Knepley PetscInt dof; 58595f82726aSMatthew G. Knepley 58605f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58615f82726aSMatthew G. Knepley PetscCheck(dim == 1 || tensor || !continuous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Continuous field %" PetscInt_FMT " must have a tensor product discretization", f); 58625f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58635f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58645f82726aSMatthew G. Knepley size += dof * Nc; 58653194fc30SMatthew G. Knepley } 58669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58673194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5868bb197d40SJed Brown switch (d) { 5869babf31e0SJed Brown case 1: 58705f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58715f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5872babf31e0SJed Brown /* 5873babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5874babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5875babf31e0SJed Brown */ 5876e327e467SRezgar Shakeri if (continuous) { 5877babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58789371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58799371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5880babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5881babf31e0SJed Brown foffset = offset; 5882e327e467SRezgar Shakeri } else { 58835f82726aSMatthew G. Knepley PetscInt dof; 58845f82726aSMatthew G. Knepley 58855f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58865f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 58875f82726aSMatthew G. Knepley foffset = offset; 5888e327e467SRezgar Shakeri } 5889babf31e0SJed Brown break; 589089eabcffSMatthew G. Knepley case 2: 58913194fc30SMatthew G. Knepley /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */ 58925f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58935f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58943194fc30SMatthew G. Knepley /* The SEM order is 58953194fc30SMatthew G. Knepley 58963194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 589789eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58983194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58993194fc30SMatthew G. Knepley */ 5900e327e467SRezgar Shakeri if (continuous) { 59013194fc30SMatthew G. Knepley const PetscInt of = 0; 59023194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 59033194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 59043194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 59053194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 59063194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 59073194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 59083194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 59093194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 59103194fc30SMatthew G. Knepley PetscInt o; 59113194fc30SMatthew G. Knepley 59123194fc30SMatthew G. Knepley /* bottom */ 59133194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 59149371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 59159371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59163194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 59173194fc30SMatthew G. Knepley /* middle */ 59183194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 59193194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 59209371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 59219371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59223194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 59233194fc30SMatthew G. Knepley } 59243194fc30SMatthew G. Knepley /* top */ 59253194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 59269371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 59279371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59283194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 59293194fc30SMatthew G. Knepley foffset = offset; 5930e327e467SRezgar Shakeri } else { 59315f82726aSMatthew G. Knepley PetscInt dof; 59325f82726aSMatthew G. Knepley 59335f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59345f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 59355f82726aSMatthew G. Knepley foffset = offset; 59363194fc30SMatthew G. Knepley } 593789eabcffSMatthew G. Knepley break; 593889eabcffSMatthew G. Knepley case 3: 593989eabcffSMatthew G. Knepley /* The original hex closure is 594089eabcffSMatthew G. Knepley 594189eabcffSMatthew G. Knepley {c, 594289eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 594389eabcffSMatthew G. Knepley e_bl, e_bb, e_br, e_bf, e_tf, e_tr, e_tb, e_tl, e_rf, e_lf, e_lb, e_rb, 594489eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 594589eabcffSMatthew G. Knepley */ 59465f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59475f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 594889eabcffSMatthew G. Knepley /* The SEM order is 594989eabcffSMatthew G. Knepley Bottom Slice 595089eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 595189eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 595289eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 595389eabcffSMatthew G. Knepley 595489eabcffSMatthew G. Knepley Middle Slice (j) 595589eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 595689eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 595789eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 595889eabcffSMatthew G. Knepley 595989eabcffSMatthew G. Knepley Top Slice 596089eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 596189eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 596289eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 596389eabcffSMatthew G. Knepley */ 5964e327e467SRezgar Shakeri if (continuous) { 596589eabcffSMatthew G. Knepley const PetscInt oc = 0; 596689eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 596789eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 596889eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 596989eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 597089eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 597189eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 597289eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 597389eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 597489eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 597589eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 597689eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 597789eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 597889eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 597989eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 598089eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 598189eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 598289eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 598389eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 598489eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 598589eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 598689eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 598789eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 598889eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 598989eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 599089eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 599189eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 599289eabcffSMatthew G. Knepley PetscInt o, n; 599389eabcffSMatthew G. Knepley 599489eabcffSMatthew G. Knepley /* Bottom Slice */ 599589eabcffSMatthew G. Knepley /* bottom */ 599689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59979371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59989371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 599989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 600089eabcffSMatthew G. Knepley /* middle */ 600189eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 600289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 60039371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 60049371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 60059371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60069371c9d4SSatish Balay } 600789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 60083194fc30SMatthew G. Knepley } 600989eabcffSMatthew G. Knepley /* top */ 601089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 60119371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 60129371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 601489eabcffSMatthew G. Knepley 601589eabcffSMatthew G. Knepley /* Middle Slice */ 601689eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 601789eabcffSMatthew G. Knepley /* bottom */ 601889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 60199371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 60209371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 602189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 602289eabcffSMatthew G. Knepley /* middle */ 602389eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 602489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 60259371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60269371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 602789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 602889eabcffSMatthew G. Knepley } 602989eabcffSMatthew G. Knepley /* top */ 603089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 60319371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 60329371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 603489eabcffSMatthew G. Knepley } 603589eabcffSMatthew G. Knepley 603689eabcffSMatthew G. Knepley /* Top Slice */ 603789eabcffSMatthew G. Knepley /* bottom */ 603889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 60399371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 60409371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 604189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 604289eabcffSMatthew G. Knepley /* middle */ 604389eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 604489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 60459371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60469371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 604789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 604889eabcffSMatthew G. Knepley } 604989eabcffSMatthew G. Knepley /* top */ 605089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 60519371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 60529371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 605389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 605489eabcffSMatthew G. Knepley 605589eabcffSMatthew G. Knepley foffset = offset; 6056e327e467SRezgar Shakeri } else { 60575f82726aSMatthew G. Knepley PetscInt dof; 60585f82726aSMatthew G. Knepley 60595f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60605f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60615f82726aSMatthew G. Knepley foffset = offset; 606289eabcffSMatthew G. Knepley } 606389eabcffSMatthew G. Knepley break; 6064d71ae5a4SJacob Faibussowitsch default: 6065d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 606689eabcffSMatthew G. Knepley } 606789eabcffSMatthew G. Knepley } 606863a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 60693194fc30SMatthew G. Knepley /* Check permutation */ 60703194fc30SMatthew G. Knepley { 60713194fc30SMatthew G. Knepley PetscInt *check; 60723194fc30SMatthew G. Knepley 60739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 60741dca8a05SBarry Smith for (i = 0; i < size; ++i) { 60751dca8a05SBarry Smith check[i] = -1; 60761dca8a05SBarry Smith PetscCheck(perm[i] >= 0 && perm[i] < size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid permutation index p[%" PetscInt_FMT "] = %" PetscInt_FMT, i, perm[i]); 60771dca8a05SBarry Smith } 60783194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60791dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60809566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60813194fc30SMatthew G. Knepley } 60829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6083a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6084a05c9aa3SJed Brown PetscInt *loc_perm; 60859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6086a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6087a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6088a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6089a05c9aa3SJed Brown } 60909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6091a05c9aa3SJed Brown } 6092bb197d40SJed Brown } 60933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60943194fc30SMatthew G. Knepley } 60953194fc30SMatthew G. Knepley 6096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6097d71ae5a4SJacob Faibussowitsch { 6098e071409bSToby Isaac PetscDS prob; 6099e071409bSToby Isaac PetscInt depth, Nf, h; 6100e071409bSToby Isaac DMLabel label; 6101e071409bSToby Isaac 6102e071409bSToby Isaac PetscFunctionBeginHot; 61039566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6104e071409bSToby Isaac Nf = prob->Nf; 6105e071409bSToby Isaac label = dm->depthLabel; 6106e071409bSToby Isaac *dspace = NULL; 6107e071409bSToby Isaac if (field < Nf) { 6108e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6109e071409bSToby Isaac 6110e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6111e071409bSToby Isaac PetscDualSpace dsp; 6112e071409bSToby Isaac 61139566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 61149566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 61159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6116e071409bSToby Isaac h = depth - 1 - h; 6117e071409bSToby Isaac if (h) { 61189566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6119e071409bSToby Isaac } else { 6120e071409bSToby Isaac *dspace = dsp; 6121e071409bSToby Isaac } 6122e071409bSToby Isaac } 6123e071409bSToby Isaac } 61243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6125e071409bSToby Isaac } 6126e071409bSToby Isaac 6127d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6128d71ae5a4SJacob Faibussowitsch { 612928351e22SJed Brown PetscScalar *array; 613028351e22SJed Brown const PetscScalar *vArray; 6131d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 61321a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6133552f7358SJed Brown 61341b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61393f7cbbe7SMatthew G. Knepley if (!values || !*values) { 61409df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61419df71ca4SMatthew G. Knepley PetscInt dof; 6142d9917b9dSMatthew G. Knepley 61439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61449df71ca4SMatthew G. Knepley size += dof; 61459df71ca4SMatthew G. Knepley } 61469df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61479df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61482a3aaacfSMatthew G. Knepley PetscInt dof; 61495a1bb5cfSMatthew G. Knepley 61505a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61525a1bb5cfSMatthew G. Knepley size += dof; 61535a1bb5cfSMatthew G. Knepley } 61543f7cbbe7SMatthew G. Knepley if (!values) { 61553f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 61563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61573f7cbbe7SMatthew G. Knepley } 61589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6159982e9ed1SMatthew G. Knepley } else { 6160982e9ed1SMatthew G. Knepley array = *values; 6161982e9ed1SMatthew G. Knepley } 61629df71ca4SMatthew G. Knepley size = 0; 616328351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 61649df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61659df71ca4SMatthew G. Knepley PetscInt dof, off, d; 616628351e22SJed Brown const PetscScalar *varr; 6167d9917b9dSMatthew G. Knepley 61689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61708e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6171ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61729df71ca4SMatthew G. Knepley size += dof; 61739df71ca4SMatthew G. Knepley } 61749df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61759df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61769df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61775a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 617828351e22SJed Brown const PetscScalar *varr; 61795a1bb5cfSMatthew G. Knepley 618052ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61838e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 61845a1bb5cfSMatthew G. Knepley if (o >= 0) { 6185ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61865a1bb5cfSMatthew G. Knepley } else { 6187ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61885a1bb5cfSMatthew G. Knepley } 61899df71ca4SMatthew G. Knepley size += dof; 61905a1bb5cfSMatthew G. Knepley } 619128351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61929df71ca4SMatthew G. Knepley if (!*values) { 61935a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61945a1bb5cfSMatthew G. Knepley *values = array; 61959df71ca4SMatthew G. Knepley } else { 619663a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61978c312ff3SMatthew G. Knepley *csize = size; 61989df71ca4SMatthew G. Knepley } 61993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62005a1bb5cfSMatthew G. Knepley } 6201d9917b9dSMatthew G. Knepley 620227f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6203d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6204d71ae5a4SJacob Faibussowitsch { 620527f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 620627f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 620727f02ce8SMatthew G. Knepley 62089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 620927f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 621027f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 621127f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 621227f02ce8SMatthew G. Knepley points[q * 2] = r; 621327f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 621427f02ce8SMatthew G. Knepley ++q; 621527f02ce8SMatthew G. Knepley } 621627f02ce8SMatthew G. Knepley } 621727f02ce8SMatthew G. Knepley *numPoints = q; 62183ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 621927f02ce8SMatthew G. Knepley } 622027f02ce8SMatthew G. Knepley 622197529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 622207218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6223d71ae5a4SJacob Faibussowitsch { 622427f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6225923c78e0SToby Isaac PetscInt np, *pts = NULL; 6226923c78e0SToby Isaac 6227923c78e0SToby Isaac PetscFunctionBeginHot; 62289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 622907218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6230923c78e0SToby Isaac PetscInt dof, off; 6231923c78e0SToby Isaac 62329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 62339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 62349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6235923c78e0SToby Isaac np = dof / 2; 62368e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 623727f02ce8SMatthew G. Knepley } else { 623807218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 62399566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6240923c78e0SToby Isaac } 6241923c78e0SToby Isaac *numPoints = np; 6242923c78e0SToby Isaac *points = pts; 6243923c78e0SToby Isaac *clp = cla; 62443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6245923c78e0SToby Isaac } 6246923c78e0SToby Isaac 6247d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6248d71ae5a4SJacob Faibussowitsch { 6249923c78e0SToby Isaac PetscFunctionBeginHot; 6250923c78e0SToby Isaac if (!*clPoints) { 62519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6252923c78e0SToby Isaac } else { 62539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6254923c78e0SToby Isaac } 6255923c78e0SToby Isaac *numPoints = 0; 6256923c78e0SToby Isaac *points = NULL; 6257923c78e0SToby Isaac *clSec = NULL; 6258923c78e0SToby Isaac *clPoints = NULL; 6259923c78e0SToby Isaac *clp = NULL; 62603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6261923c78e0SToby Isaac } 6262923c78e0SToby Isaac 6263d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 6264d71ae5a4SJacob Faibussowitsch { 62651a271a75SMatthew G. Knepley PetscInt offset = 0, p; 626697e99dd9SToby Isaac const PetscInt **perms = NULL; 626797e99dd9SToby Isaac const PetscScalar **flips = NULL; 62681a271a75SMatthew G. Knepley 62691a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6270fe02ba77SJed Brown *size = 0; 62719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 627297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 627397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 627497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 627597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62761a271a75SMatthew G. Knepley PetscInt dof, off, d; 62771a271a75SMatthew G. Knepley const PetscScalar *varr; 62781a271a75SMatthew G. Knepley 62799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62818e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 628297e99dd9SToby Isaac if (clperm) { 628397e99dd9SToby Isaac if (perm) { 628497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62851a271a75SMatthew G. Knepley } else { 628697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 628797e99dd9SToby Isaac } 628897e99dd9SToby Isaac if (flip) { 628997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 629097e99dd9SToby Isaac } 629197e99dd9SToby Isaac } else { 629297e99dd9SToby Isaac if (perm) { 629397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 629497e99dd9SToby Isaac } else { 629597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 629697e99dd9SToby Isaac } 629797e99dd9SToby Isaac if (flip) { 629897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62991a271a75SMatthew G. Knepley } 63001a271a75SMatthew G. Knepley } 630197e99dd9SToby Isaac offset += dof; 630297e99dd9SToby Isaac } 63039566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 63041a271a75SMatthew G. Knepley *size = offset; 63053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63061a271a75SMatthew G. Knepley } 63071a271a75SMatthew G. Knepley 6308d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 6309d71ae5a4SJacob Faibussowitsch { 63101a271a75SMatthew G. Knepley PetscInt offset = 0, f; 63111a271a75SMatthew G. Knepley 63121a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6313fe02ba77SJed Brown *size = 0; 63141a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 631597e99dd9SToby Isaac PetscInt p; 631697e99dd9SToby Isaac const PetscInt **perms = NULL; 631797e99dd9SToby Isaac const PetscScalar **flips = NULL; 63181a271a75SMatthew G. Knepley 63199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 632097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 632297e99dd9SToby Isaac PetscInt fdof, foff, b; 63231a271a75SMatthew G. Knepley const PetscScalar *varr; 632497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63261a271a75SMatthew G. Knepley 63279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63291a271a75SMatthew G. Knepley varr = &vArray[foff]; 633097e99dd9SToby Isaac if (clperm) { 63319371c9d4SSatish Balay if (perm) { 6332ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 63331a271a75SMatthew G. Knepley } else { 6334ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 63359371c9d4SSatish Balay } 63369371c9d4SSatish Balay if (flip) { 6337ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 63389371c9d4SSatish Balay } 63399371c9d4SSatish Balay } else { 63409371c9d4SSatish Balay if (perm) { 6341ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 63429371c9d4SSatish Balay } else { 6343ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 63449371c9d4SSatish Balay } 63459371c9d4SSatish Balay if (flip) { 6346ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 63479371c9d4SSatish Balay } 63481a271a75SMatthew G. Knepley } 634997e99dd9SToby Isaac offset += fdof; 63501a271a75SMatthew G. Knepley } 63519566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63521a271a75SMatthew G. Knepley } 63531a271a75SMatthew G. Knepley *size = offset; 63543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63551a271a75SMatthew G. Knepley } 63561a271a75SMatthew G. Knepley 6357e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 635807218a29SMatthew G. Knepley { 635907218a29SMatthew G. Knepley PetscSection clSection; 636007218a29SMatthew G. Knepley IS clPoints; 636107218a29SMatthew G. Knepley PetscInt *points = NULL; 6362e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 636307218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 636407218a29SMatthew G. Knepley 636507218a29SMatthew G. Knepley PetscFunctionBeginHot; 636607218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 636707218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 636807218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6369e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 637007218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 637107218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 637207218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 637307218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 637407218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 637507218a29SMatthew G. Knepley } 637607218a29SMatthew G. Knepley /* Get points */ 637707218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 637807218a29SMatthew G. Knepley /* Get sizes */ 637907218a29SMatthew G. Knepley asize = 0; 638007218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 638107218a29SMatthew G. Knepley PetscInt dof; 638207218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 638307218a29SMatthew G. Knepley asize += dof; 638407218a29SMatthew G. Knepley } 638507218a29SMatthew G. Knepley if (values) { 638607218a29SMatthew G. Knepley const PetscScalar *vArray; 638707218a29SMatthew G. Knepley PetscInt size; 638807218a29SMatthew G. Knepley 638907218a29SMatthew G. Knepley if (*values) { 639007218a29SMatthew G. Knepley PetscCheck(*csize >= asize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %" PetscInt_FMT " not sufficient to hold closure size %" PetscInt_FMT, *csize, asize); 639107218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6392e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 639307218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 639407218a29SMatthew G. Knepley /* Get values */ 639507218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 639607218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 639707218a29SMatthew G. Knepley PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size); 639807218a29SMatthew G. Knepley /* Cleanup array */ 639907218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 640007218a29SMatthew G. Knepley } 640107218a29SMatthew G. Knepley if (csize) *csize = asize; 640207218a29SMatthew G. Knepley /* Cleanup points */ 640307218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 640407218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 640507218a29SMatthew G. Knepley } 640607218a29SMatthew G. Knepley 6407552f7358SJed Brown /*@C 6408552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6409552f7358SJed Brown 6410552f7358SJed Brown Not collective 6411552f7358SJed Brown 6412552f7358SJed Brown Input Parameters: 6413a1cb98faSBarry Smith + dm - The `DM` 641420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6415552f7358SJed Brown . v - The local vector 6416a1cb98faSBarry Smith - point - The point in the `DM` 6417552f7358SJed Brown 64186b867d5aSJose E. Roman Input/Output Parameters: 641920f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 642020f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 642120f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 642222c1ee49SMatthew G. Knepley 6423552f7358SJed Brown Level: intermediate 6424552f7358SJed Brown 6425a1cb98faSBarry Smith Notes: 642620f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6427a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6428a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6429a1cb98faSBarry Smith 6430a1cb98faSBarry Smith A typical use could be 6431a1cb98faSBarry Smith .vb 6432a1cb98faSBarry Smith values = NULL; 6433a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6434a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6435a1cb98faSBarry Smith <Compute on closure> 6436a1cb98faSBarry Smith } 6437a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6438a1cb98faSBarry Smith .ve 6439a1cb98faSBarry Smith or 6440a1cb98faSBarry Smith .vb 6441a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6442a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6443a1cb98faSBarry Smith clSize = clMaxSize; 6444a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6445a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6446a1cb98faSBarry Smith <Compute on closure> 6447a1cb98faSBarry Smith } 6448a1cb98faSBarry Smith } 6449a1cb98faSBarry Smith PetscFree(values); 6450a1cb98faSBarry Smith .ve 6451a1cb98faSBarry Smith 645260225df5SJacob Faibussowitsch Fortran Notes: 645320f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6454a1cb98faSBarry Smith 64551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6456552f7358SJed Brown @*/ 6457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6458d71ae5a4SJacob Faibussowitsch { 6459d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6460e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 64613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6462552f7358SJed Brown } 6463552f7358SJed Brown 6464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6465d71ae5a4SJacob Faibussowitsch { 6466e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6467e5c487bfSMatthew G. Knepley PetscSection clSection; 6468e5c487bfSMatthew G. Knepley IS clPoints; 6469e5c487bfSMatthew G. Knepley PetscScalar *array; 6470e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6471e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6472c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6473c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6474e5c487bfSMatthew G. Knepley 6475e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6476e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64779566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6478e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6479e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6483e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64849566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6486e5c487bfSMatthew G. Knepley } 6487e5c487bfSMatthew G. Knepley /* Get points */ 648807218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6489c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6490c459fbc1SJed Brown PetscInt dof; 64919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6492c459fbc1SJed Brown clsize += dof; 6493c459fbc1SJed Brown } 64949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6495e5c487bfSMatthew G. Knepley /* Filter points */ 6496e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6497e5c487bfSMatthew G. Knepley PetscInt dep; 6498e5c487bfSMatthew G. Knepley 64999566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6500e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6501e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6502e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6503e5c487bfSMatthew G. Knepley ++Np; 6504e5c487bfSMatthew G. Knepley } 6505e5c487bfSMatthew G. Knepley /* Get array */ 6506e5c487bfSMatthew G. Knepley if (!values || !*values) { 6507e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6508e5c487bfSMatthew G. Knepley 6509e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 65109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6511e5c487bfSMatthew G. Knepley asize += dof; 6512e5c487bfSMatthew G. Knepley } 6513e5c487bfSMatthew G. Knepley if (!values) { 65149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6515e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 65163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6517e5c487bfSMatthew G. Knepley } 65189566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6519e5c487bfSMatthew G. Knepley } else { 6520e5c487bfSMatthew G. Knepley array = *values; 6521e5c487bfSMatthew G. Knepley } 65229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6523e5c487bfSMatthew G. Knepley /* Get values */ 65249566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 65259566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6526e5c487bfSMatthew G. Knepley /* Cleanup points */ 65279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6528e5c487bfSMatthew G. Knepley /* Cleanup array */ 65299566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6530e5c487bfSMatthew G. Knepley if (!*values) { 6531e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6532e5c487bfSMatthew G. Knepley *values = array; 6533e5c487bfSMatthew G. Knepley } else { 653463a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6535e5c487bfSMatthew G. Knepley *csize = size; 6536e5c487bfSMatthew G. Knepley } 65373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6538e5c487bfSMatthew G. Knepley } 6539e5c487bfSMatthew G. Knepley 6540552f7358SJed Brown /*@C 6541552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6542552f7358SJed Brown 6543552f7358SJed Brown Not collective 6544552f7358SJed Brown 6545552f7358SJed Brown Input Parameters: 6546a1cb98faSBarry Smith + dm - The `DM` 654720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6548552f7358SJed Brown . v - The local vector 6549a1cb98faSBarry Smith . point - The point in the `DM` 655020f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6551552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6552552f7358SJed Brown 6553552f7358SJed Brown Level: intermediate 6554552f7358SJed Brown 6555a1cb98faSBarry Smith Note: 655620f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6557a1cb98faSBarry Smith 655860225df5SJacob Faibussowitsch Fortran Notes: 655920f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6560a1cb98faSBarry Smith 65611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6562552f7358SJed Brown @*/ 6563d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6564d71ae5a4SJacob Faibussowitsch { 6565552f7358SJed Brown PetscInt size = 0; 6566552f7358SJed Brown 6567552f7358SJed Brown PetscFunctionBegin; 6568552f7358SJed Brown /* Should work without recalculating size */ 65699566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6570c9fdaa05SMatthew G. Knepley *values = NULL; 65713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6572552f7358SJed Brown } 6573552f7358SJed Brown 6574d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6575d71ae5a4SJacob Faibussowitsch { 65769371c9d4SSatish Balay *x += y; 65779371c9d4SSatish Balay } 6578d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6579d71ae5a4SJacob Faibussowitsch { 65809371c9d4SSatish Balay *x = y; 65819371c9d4SSatish Balay } 6582552f7358SJed Brown 6583d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 6584d71ae5a4SJacob Faibussowitsch { 6585552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6586552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6587552f7358SJed Brown PetscScalar *a; 6588552f7358SJed Brown PetscInt off, cind = 0, k; 6589552f7358SJed Brown 6590552f7358SJed Brown PetscFunctionBegin; 65919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6593552f7358SJed Brown a = &array[off]; 6594552f7358SJed Brown if (!cdof || setBC) { 659597e99dd9SToby Isaac if (clperm) { 65969371c9d4SSatish Balay if (perm) { 6597ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6598552f7358SJed Brown } else { 6599ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 66009371c9d4SSatish Balay } 66019371c9d4SSatish Balay } else { 66029371c9d4SSatish Balay if (perm) { 6603ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 66049371c9d4SSatish Balay } else { 6605ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 66069371c9d4SSatish Balay } 6607552f7358SJed Brown } 6608552f7358SJed Brown } else { 66099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 661097e99dd9SToby Isaac if (clperm) { 66119371c9d4SSatish Balay if (perm) { 66129371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 66139371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66149371c9d4SSatish Balay ++cind; 66159371c9d4SSatish Balay continue; 66169371c9d4SSatish Balay } 661797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6618552f7358SJed Brown } 6619552f7358SJed Brown } else { 6620552f7358SJed Brown for (k = 0; k < dof; ++k) { 66219371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66229371c9d4SSatish Balay ++cind; 66239371c9d4SSatish Balay continue; 66249371c9d4SSatish Balay } 662597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 662697e99dd9SToby Isaac } 662797e99dd9SToby Isaac } 662897e99dd9SToby Isaac } else { 662997e99dd9SToby Isaac if (perm) { 663097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66319371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66329371c9d4SSatish Balay ++cind; 66339371c9d4SSatish Balay continue; 66349371c9d4SSatish Balay } 663597e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 663697e99dd9SToby Isaac } 663797e99dd9SToby Isaac } else { 663897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66399371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66409371c9d4SSatish Balay ++cind; 66419371c9d4SSatish Balay continue; 66429371c9d4SSatish Balay } 664397e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 664497e99dd9SToby Isaac } 6645552f7358SJed Brown } 6646552f7358SJed Brown } 6647552f7358SJed Brown } 66483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6649552f7358SJed Brown } 6650552f7358SJed Brown 6651d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[]) 6652d71ae5a4SJacob Faibussowitsch { 6653a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6654a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6655a5e93ea8SMatthew G. Knepley PetscScalar *a; 6656a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6657a5e93ea8SMatthew G. Knepley 6658a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 66609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6661a5e93ea8SMatthew G. Knepley a = &array[off]; 6662a5e93ea8SMatthew G. Knepley if (cdof) { 66639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 666497e99dd9SToby Isaac if (clperm) { 666597e99dd9SToby Isaac if (perm) { 6666a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6667a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 666997e99dd9SToby Isaac cind++; 6670a5e93ea8SMatthew G. Knepley } 6671a5e93ea8SMatthew G. Knepley } 6672a5e93ea8SMatthew G. Knepley } else { 6673a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6674a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 667597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 667697e99dd9SToby Isaac cind++; 667797e99dd9SToby Isaac } 667897e99dd9SToby Isaac } 667997e99dd9SToby Isaac } 668097e99dd9SToby Isaac } else { 668197e99dd9SToby Isaac if (perm) { 668297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668497e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 668597e99dd9SToby Isaac cind++; 668697e99dd9SToby Isaac } 668797e99dd9SToby Isaac } 668897e99dd9SToby Isaac } else { 668997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 669097e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 669197e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 669297e99dd9SToby Isaac cind++; 669397e99dd9SToby Isaac } 6694a5e93ea8SMatthew G. Knepley } 6695a5e93ea8SMatthew G. Knepley } 6696a5e93ea8SMatthew G. Knepley } 6697a5e93ea8SMatthew G. Knepley } 66983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6699a5e93ea8SMatthew G. Knepley } 6700a5e93ea8SMatthew G. Knepley 6701d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 6702d71ae5a4SJacob Faibussowitsch { 6703552f7358SJed Brown PetscScalar *a; 67041a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67051a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 670697e99dd9SToby Isaac PetscInt cind = 0, b; 6707552f7358SJed Brown 6708552f7358SJed Brown PetscFunctionBegin; 67099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67121a271a75SMatthew G. Knepley a = &array[foff]; 6713552f7358SJed Brown if (!fcdof || setBC) { 671497e99dd9SToby Isaac if (clperm) { 67159371c9d4SSatish Balay if (perm) { 6716ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6717552f7358SJed Brown } else { 6718ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 67199371c9d4SSatish Balay } 67209371c9d4SSatish Balay } else { 67219371c9d4SSatish Balay if (perm) { 6722ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 67239371c9d4SSatish Balay } else { 6724ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 67259371c9d4SSatish Balay } 6726552f7358SJed Brown } 6727552f7358SJed Brown } else { 67289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672997e99dd9SToby Isaac if (clperm) { 673097e99dd9SToby Isaac if (perm) { 673197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67329371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67339371c9d4SSatish Balay ++cind; 67349371c9d4SSatish Balay continue; 67359371c9d4SSatish Balay } 673697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6737552f7358SJed Brown } 6738552f7358SJed Brown } else { 673997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67409371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67419371c9d4SSatish Balay ++cind; 67429371c9d4SSatish Balay continue; 67439371c9d4SSatish Balay } 674497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 674597e99dd9SToby Isaac } 674697e99dd9SToby Isaac } 674797e99dd9SToby Isaac } else { 674897e99dd9SToby Isaac if (perm) { 674997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67509371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67519371c9d4SSatish Balay ++cind; 67529371c9d4SSatish Balay continue; 67539371c9d4SSatish Balay } 675497e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 675597e99dd9SToby Isaac } 675697e99dd9SToby Isaac } else { 675797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67589371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67599371c9d4SSatish Balay ++cind; 67609371c9d4SSatish Balay continue; 67619371c9d4SSatish Balay } 676297e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6763552f7358SJed Brown } 6764552f7358SJed Brown } 6765552f7358SJed Brown } 6766552f7358SJed Brown } 67671a271a75SMatthew G. Knepley *offset += fdof; 67683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6769552f7358SJed Brown } 6770552f7358SJed Brown 6771d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar *, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 6772d71ae5a4SJacob Faibussowitsch { 6773a5e93ea8SMatthew G. Knepley PetscScalar *a; 67741a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67751a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67765da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6777ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6778a5e93ea8SMatthew G. Knepley 6779a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67841a271a75SMatthew G. Knepley a = &array[foff]; 6785a5e93ea8SMatthew G. Knepley if (fcdof) { 6786ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 678897e99dd9SToby Isaac if (clperm) { 678997e99dd9SToby Isaac if (perm) { 6790ba322698SMatthew G. Knepley if (comps) { 6791ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6792ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67939371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67949371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67959371c9d4SSatish Balay ncSet = PETSC_TRUE; 67969371c9d4SSatish Balay } 67979371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67989371c9d4SSatish Balay ++cind; 67999371c9d4SSatish Balay fcSet = PETSC_TRUE; 68009371c9d4SSatish Balay } 6801ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6802ba322698SMatthew G. Knepley } 6803ba322698SMatthew G. Knepley } else { 680497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 680597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 680697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6807a5e93ea8SMatthew G. Knepley ++cind; 6808a5e93ea8SMatthew G. Knepley } 6809a5e93ea8SMatthew G. Knepley } 6810ba322698SMatthew G. Knepley } 6811ba322698SMatthew G. Knepley } else { 6812ba322698SMatthew G. Knepley if (comps) { 6813ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6814ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68159371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68169371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68179371c9d4SSatish Balay ncSet = PETSC_TRUE; 68189371c9d4SSatish Balay } 68199371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68209371c9d4SSatish Balay ++cind; 68219371c9d4SSatish Balay fcSet = PETSC_TRUE; 68229371c9d4SSatish Balay } 6823ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6824ba322698SMatthew G. Knepley } 6825a5e93ea8SMatthew G. Knepley } else { 682697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 682797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 682897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 682997e99dd9SToby Isaac ++cind; 683097e99dd9SToby Isaac } 683197e99dd9SToby Isaac } 683297e99dd9SToby Isaac } 6833ba322698SMatthew G. Knepley } 683497e99dd9SToby Isaac } else { 683597e99dd9SToby Isaac if (perm) { 6836ba322698SMatthew G. Knepley if (comps) { 6837ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6838ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68399371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68409371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68419371c9d4SSatish Balay ncSet = PETSC_TRUE; 68429371c9d4SSatish Balay } 68439371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68449371c9d4SSatish Balay ++cind; 68459371c9d4SSatish Balay fcSet = PETSC_TRUE; 68469371c9d4SSatish Balay } 6847ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6848ba322698SMatthew G. Knepley } 6849ba322698SMatthew G. Knepley } else { 685097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 685197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 685297e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 685397e99dd9SToby Isaac ++cind; 685497e99dd9SToby Isaac } 685597e99dd9SToby Isaac } 6856ba322698SMatthew G. Knepley } 6857ba322698SMatthew G. Knepley } else { 6858ba322698SMatthew G. Knepley if (comps) { 6859ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6860ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68619371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68629371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68639371c9d4SSatish Balay ncSet = PETSC_TRUE; 68649371c9d4SSatish Balay } 68659371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68669371c9d4SSatish Balay ++cind; 68679371c9d4SSatish Balay fcSet = PETSC_TRUE; 68689371c9d4SSatish Balay } 6869ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6870ba322698SMatthew G. Knepley } 687197e99dd9SToby Isaac } else { 687297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 687397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 687497e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6875a5e93ea8SMatthew G. Knepley ++cind; 6876a5e93ea8SMatthew G. Knepley } 6877a5e93ea8SMatthew G. Knepley } 6878a5e93ea8SMatthew G. Knepley } 6879a5e93ea8SMatthew G. Knepley } 6880a5e93ea8SMatthew G. Knepley } 6881ba322698SMatthew G. Knepley } 68821a271a75SMatthew G. Knepley *offset += fdof; 68833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6884a5e93ea8SMatthew G. Knepley } 6885a5e93ea8SMatthew G. Knepley 6886d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6887d71ae5a4SJacob Faibussowitsch { 6888552f7358SJed Brown PetscScalar *array; 68891b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68901b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6891552f7358SJed Brown 68921b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68969566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68979566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6898b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6899b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6900b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6901b6ebb6e6SMatthew G. Knepley 69029371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 69039371c9d4SSatish Balay dof = 0; 69049371c9d4SSatish Balay continue; 69059371c9d4SSatish Balay } 69069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6907b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6908b6ebb6e6SMatthew G. Knepley { 6909b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6910b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6911b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6912b6ebb6e6SMatthew G. Knepley 69139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 69149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6915b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6916b6ebb6e6SMatthew G. Knepley if (!cdof) { 6917b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6918ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6919b6ebb6e6SMatthew G. Knepley } else { 6920ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6921b6ebb6e6SMatthew G. Knepley } 6922b6ebb6e6SMatthew G. Knepley } else { 69239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6924b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6925b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69269371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69279371c9d4SSatish Balay ++cind; 69289371c9d4SSatish Balay continue; 69299371c9d4SSatish Balay } 6930b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6931b6ebb6e6SMatthew G. Knepley } 6932b6ebb6e6SMatthew G. Knepley } else { 6933b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69349371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69359371c9d4SSatish Balay ++cind; 69369371c9d4SSatish Balay continue; 69379371c9d4SSatish Balay } 6938b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6939b6ebb6e6SMatthew G. Knepley } 6940b6ebb6e6SMatthew G. Knepley } 6941b6ebb6e6SMatthew G. Knepley } 6942b6ebb6e6SMatthew G. Knepley } 6943b6ebb6e6SMatthew G. Knepley } 69449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6946b6ebb6e6SMatthew G. Knepley } 69471b406b76SMatthew G. Knepley 69481b406b76SMatthew G. Knepley /*@C 694920f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 69501b406b76SMatthew G. Knepley 69511b406b76SMatthew G. Knepley Not collective 69521b406b76SMatthew G. Knepley 69531b406b76SMatthew G. Knepley Input Parameters: 6954a1cb98faSBarry Smith + dm - The `DM` 695520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 69561b406b76SMatthew G. Knepley . v - The local vector 695720f4b53cSBarry Smith . point - The point in the `DM` 69581b406b76SMatthew G. Knepley . values - The array of values 6959a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6960a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 69611b406b76SMatthew G. Knepley 69621b406b76SMatthew G. Knepley Level: intermediate 69631b406b76SMatthew G. Knepley 69641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 69651b406b76SMatthew G. Knepley @*/ 6966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6967d71ae5a4SJacob Faibussowitsch { 69681b406b76SMatthew G. Knepley PetscSection clSection; 69691b406b76SMatthew G. Knepley IS clPoints; 69701b406b76SMatthew G. Knepley PetscScalar *array; 69711b406b76SMatthew G. Knepley PetscInt *points = NULL; 697227f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6973c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 69741b406b76SMatthew G. Knepley 69751a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69761b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69779566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69781a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69791a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69821b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69839566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69851b406b76SMatthew G. Knepley } 69861a271a75SMatthew G. Knepley /* Get points */ 698707218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6988c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6989c459fbc1SJed Brown PetscInt dof; 69909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6991c459fbc1SJed Brown clsize += dof; 6992c459fbc1SJed Brown } 69939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69941a271a75SMatthew G. Knepley /* Get array */ 69959566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69961a271a75SMatthew G. Knepley /* Get values */ 6997ef90cfe2SMatthew G. Knepley if (numFields > 0) { 699897e99dd9SToby Isaac PetscInt offset = 0, f; 6999552f7358SJed Brown for (f = 0; f < numFields; ++f) { 700097e99dd9SToby Isaac const PetscInt **perms = NULL; 700197e99dd9SToby Isaac const PetscScalar **flips = NULL; 700297e99dd9SToby Isaac 70039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7004552f7358SJed Brown switch (mode) { 7005552f7358SJed Brown case INSERT_VALUES: 700697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70103ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 70119371c9d4SSatish Balay } 70129371c9d4SSatish Balay break; 7013552f7358SJed Brown case INSERT_ALL_VALUES: 701497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 701597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70183ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 70199371c9d4SSatish Balay } 70209371c9d4SSatish Balay break; 7021a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 702297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70263ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 70279371c9d4SSatish Balay } 70289371c9d4SSatish Balay break; 7029552f7358SJed Brown case ADD_VALUES: 703097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70343ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 70359371c9d4SSatish Balay } 70369371c9d4SSatish Balay break; 7037552f7358SJed Brown case ADD_ALL_VALUES: 703897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70423ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 70439371c9d4SSatish Balay } 70449371c9d4SSatish Balay break; 7045304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 704697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 704797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70503ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 70519371c9d4SSatish Balay } 70529371c9d4SSatish Balay break; 7053d71ae5a4SJacob Faibussowitsch default: 7054d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7055552f7358SJed Brown } 70569566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 70571a271a75SMatthew G. Knepley } 7058552f7358SJed Brown } else { 70591a271a75SMatthew G. Knepley PetscInt dof, off; 706097e99dd9SToby Isaac const PetscInt **perms = NULL; 706197e99dd9SToby Isaac const PetscScalar **flips = NULL; 70621a271a75SMatthew G. Knepley 70639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7064552f7358SJed Brown switch (mode) { 7065552f7358SJed Brown case INSERT_VALUES: 706697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70713ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70729371c9d4SSatish Balay } 70739371c9d4SSatish Balay break; 7074552f7358SJed Brown case INSERT_ALL_VALUES: 707597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 707897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70803ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70819371c9d4SSatish Balay } 70829371c9d4SSatish Balay break; 7083a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 708497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 708597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70893ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70909371c9d4SSatish Balay } 70919371c9d4SSatish Balay break; 7092552f7358SJed Brown case ADD_VALUES: 709397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 709497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 709597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70983ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70999371c9d4SSatish Balay } 71009371c9d4SSatish Balay break; 7101552f7358SJed Brown case ADD_ALL_VALUES: 710297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 710397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 710497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 710597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71073ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 71089371c9d4SSatish Balay } 71099371c9d4SSatish Balay break; 7110304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 711197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 711297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 711397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 711497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71163ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 71179371c9d4SSatish Balay } 71189371c9d4SSatish Balay break; 7119d71ae5a4SJacob Faibussowitsch default: 7120d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7121552f7358SJed Brown } 71229566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7123552f7358SJed Brown } 71241a271a75SMatthew G. Knepley /* Cleanup points */ 71259566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 71261a271a75SMatthew G. Knepley /* Cleanup array */ 71279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7129552f7358SJed Brown } 7130552f7358SJed Brown 71315f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7132d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7133d71ae5a4SJacob Faibussowitsch { 71345f790a90SMatthew G. Knepley PetscFunctionBegin; 713511cc89d2SBarry Smith *contains = PETSC_TRUE; 71365f790a90SMatthew G. Knepley if (label) { 7137d6177c40SToby Isaac PetscInt fdof; 71385f790a90SMatthew G. Knepley 713911cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 714011cc89d2SBarry Smith if (!*contains) { 71419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71425f790a90SMatthew G. Knepley *offset += fdof; 71433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71445f790a90SMatthew G. Knepley } 71455f790a90SMatthew G. Knepley } 71463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71475f790a90SMatthew G. Knepley } 71485f790a90SMatthew G. Knepley 714997529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode) 7151d71ae5a4SJacob Faibussowitsch { 7152e07394fbSMatthew G. Knepley PetscSection clSection; 7153e07394fbSMatthew G. Knepley IS clPoints; 7154e07394fbSMatthew G. Knepley PetscScalar *array; 7155e07394fbSMatthew G. Knepley PetscInt *points = NULL; 715697529cf3SJed Brown const PetscInt *clp; 7157e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 715897e99dd9SToby Isaac PetscInt offset = 0, f; 7159e07394fbSMatthew G. Knepley 7160e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7161e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71629566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7163e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7164e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7166e07394fbSMatthew G. Knepley /* Get points */ 716707218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7168e07394fbSMatthew G. Knepley /* Get array */ 71699566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7170e07394fbSMatthew G. Knepley /* Get values */ 7171e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 717297e99dd9SToby Isaac const PetscInt **perms = NULL; 717397e99dd9SToby Isaac const PetscScalar **flips = NULL; 717411cc89d2SBarry Smith PetscBool contains; 717597e99dd9SToby Isaac 7176e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7177e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7178e07394fbSMatthew G. Knepley PetscInt fdof; 71799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7180e07394fbSMatthew G. Knepley offset += fdof; 7181e07394fbSMatthew G. Knepley } 7182e07394fbSMatthew G. Knepley continue; 7183e07394fbSMatthew G. Knepley } 71849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7185e07394fbSMatthew G. Knepley switch (mode) { 7186e07394fbSMatthew G. Knepley case INSERT_VALUES: 718797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 718897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 718997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 719097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 719111cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 719211cc89d2SBarry Smith if (!contains) continue; 71939566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71949371c9d4SSatish Balay } 71959371c9d4SSatish Balay break; 7196e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 719797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 719897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 720111cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 720211cc89d2SBarry Smith if (!contains) continue; 72039566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 72049371c9d4SSatish Balay } 72059371c9d4SSatish Balay break; 7206e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 720797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 720897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 721111cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 721211cc89d2SBarry Smith if (!contains) continue; 72139566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 72149371c9d4SSatish Balay } 72159371c9d4SSatish Balay break; 7216e07394fbSMatthew G. Knepley case ADD_VALUES: 721797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 721897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 722111cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 722211cc89d2SBarry Smith if (!contains) continue; 72239566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 72249371c9d4SSatish Balay } 72259371c9d4SSatish Balay break; 7226e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 722797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 722897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 723097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 723111cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 723211cc89d2SBarry Smith if (!contains) continue; 72339566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 72349371c9d4SSatish Balay } 72359371c9d4SSatish Balay break; 7236d71ae5a4SJacob Faibussowitsch default: 7237d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7238e07394fbSMatthew G. Knepley } 72399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7240e07394fbSMatthew G. Knepley } 7241e07394fbSMatthew G. Knepley /* Cleanup points */ 72429566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7243e07394fbSMatthew G. Knepley /* Cleanup array */ 72449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7246e07394fbSMatthew G. Knepley } 7247e07394fbSMatthew G. Knepley 7248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7249d71ae5a4SJacob Faibussowitsch { 7250552f7358SJed Brown PetscMPIInt rank; 7251552f7358SJed Brown PetscInt i, j; 7252552f7358SJed Brown 7253552f7358SJed Brown PetscFunctionBegin; 72549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 725563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 725663a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 725763a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7258b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 72593ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7260b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 72619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7262b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7263519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 72649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7265552f7358SJed Brown #else 72669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7267552f7358SJed Brown #endif 7268552f7358SJed Brown } 72699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7270552f7358SJed Brown } 72713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7272552f7358SJed Brown } 7273552f7358SJed Brown 727405586334SMatthew G. Knepley /* 727505586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 727605586334SMatthew G. Knepley 727705586334SMatthew G. Knepley Input Parameters: 727805586334SMatthew G. Knepley + section - The section for this data layout 727936fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 728005586334SMatthew G. Knepley . point - The point contributing dofs with these indices 728105586334SMatthew G. Knepley . off - The global offset of this point 728205586334SMatthew G. Knepley . loff - The local offset of each field 7283a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 728405586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 728505586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 728605586334SMatthew G. Knepley 728705586334SMatthew G. Knepley Output Parameter: 728805586334SMatthew G. Knepley . indices - Indices for dofs on this point 728905586334SMatthew G. Knepley 729005586334SMatthew G. Knepley Level: developer 729105586334SMatthew G. Knepley 729205586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 729305586334SMatthew G. Knepley */ 7294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7295d71ae5a4SJacob Faibussowitsch { 7296e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7297552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7298552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7299552f7358SJed Brown PetscInt cind = 0, k; 7300552f7358SJed Brown 7301552f7358SJed Brown PetscFunctionBegin; 730208401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 73049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7305552f7358SJed Brown if (!cdof || setBC) { 730605586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 730705586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730905586334SMatthew G. Knepley 731005586334SMatthew G. Knepley indices[ind] = off + k; 7311552f7358SJed Brown } 7312552f7358SJed Brown } else { 73139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 73144acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 731505586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 731605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731705586334SMatthew G. Knepley 73184acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 73194acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 732005586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 73214acb8e1eSToby Isaac ++cind; 73224acb8e1eSToby Isaac } else { 732336fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7324552f7358SJed Brown } 7325552f7358SJed Brown } 7326552f7358SJed Brown } 7327e6ccafaeSMatthew G Knepley *loff += dof; 73283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7329552f7358SJed Brown } 7330552f7358SJed Brown 73317e29afd2SMatthew G. Knepley /* 733236fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 73337e29afd2SMatthew G. Knepley 733436fa2b79SJed Brown Input Parameters: 733536fa2b79SJed Brown + section - a section (global or local) 733620f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 733736fa2b79SJed Brown . point - point within section 733836fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 733936fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 734036fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 734136fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 734236fa2b79SJed Brown . permsoff - offset 734336fa2b79SJed Brown - indperm - index permutation 734436fa2b79SJed Brown 734536fa2b79SJed Brown Output Parameter: 734636fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 734736fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 734836fa2b79SJed Brown 734936fa2b79SJed Brown Notes: 735036fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 735136fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 735236fa2b79SJed Brown in the local vector. 735336fa2b79SJed Brown 735436fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 735536fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 735636fa2b79SJed Brown 735736fa2b79SJed Brown Developer Note: 735836fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 735936fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 736036fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 736136fa2b79SJed Brown 736236fa2b79SJed Brown Example: 736336fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 736436fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 736536fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 736636fa2b79SJed Brown The global vector does not store constrained dofs, so when this function returns global indices, say {110, -112, 111}, the value of -112 is an arbitrary flag that should not be interpreted beyond its sign. 736736fa2b79SJed Brown 736836fa2b79SJed Brown Level: developer 73697e29afd2SMatthew G. Knepley */ 7370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7371d71ae5a4SJacob Faibussowitsch { 7372552f7358SJed Brown PetscInt numFields, foff, f; 7373552f7358SJed Brown 7374552f7358SJed Brown PetscFunctionBegin; 737508401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7377552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73784acb8e1eSToby Isaac PetscInt fdof, cfdof; 7379552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73804acb8e1eSToby Isaac PetscInt cind = 0, b; 73814acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7382552f7358SJed Brown 73839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7385552f7358SJed Brown if (!cfdof || setBC) { 738605586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738705586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 738905586334SMatthew G. Knepley 739005586334SMatthew G. Knepley indices[ind] = off + foff + b; 739105586334SMatthew G. Knepley } 7392552f7358SJed Brown } else { 73939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 739405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 739505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 739605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 739705586334SMatthew G. Knepley 73984acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 739905586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7400552f7358SJed Brown ++cind; 7401552f7358SJed Brown } else { 740236fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7403552f7358SJed Brown } 7404552f7358SJed Brown } 7405552f7358SJed Brown } 740636fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7407552f7358SJed Brown foffs[f] += fdof; 7408552f7358SJed Brown } 74093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7410552f7358SJed Brown } 7411552f7358SJed Brown 74127e29afd2SMatthew G. Knepley /* 74137e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 74147e29afd2SMatthew G. Knepley 74157e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7416645102dcSJed Brown 7417645102dcSJed Brown Notes: 7418645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7419645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 74207e29afd2SMatthew G. Knepley */ 7421d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7422d71ae5a4SJacob Faibussowitsch { 74237e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 74247e29afd2SMatthew G. Knepley 74257e29afd2SMatthew G. Knepley PetscFunctionBegin; 74269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 74277e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 74287e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 74297e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 74307e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 74317e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 74327e29afd2SMatthew G. Knepley 74339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 74359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7436645102dcSJed Brown if (!cfdof) { 743705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 743905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744005586334SMatthew G. Knepley 744105586334SMatthew G. Knepley indices[ind] = foff + b; 744205586334SMatthew G. Knepley } 74437e29afd2SMatthew G. Knepley } else { 74449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 744505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 744605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 744705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744805586334SMatthew G. Knepley 74497e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 745005586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 74517e29afd2SMatthew G. Knepley ++cind; 74527e29afd2SMatthew G. Knepley } else { 745305586334SMatthew G. Knepley indices[ind] = foff + b - cind; 74547e29afd2SMatthew G. Knepley } 74557e29afd2SMatthew G. Knepley } 74567e29afd2SMatthew G. Knepley } 74577e29afd2SMatthew G. Knepley foffs[f] += fdof; 74587e29afd2SMatthew G. Knepley } 74593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74607e29afd2SMatthew G. Knepley } 74617e29afd2SMatthew G. Knepley 7462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft) 7463d71ae5a4SJacob Faibussowitsch { 7464d3d1a6afSToby Isaac Mat cMat; 7465d3d1a6afSToby Isaac PetscSection aSec, cSec; 7466d3d1a6afSToby Isaac IS aIS; 7467d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7468d3d1a6afSToby Isaac const PetscInt *anchors; 7469e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7470d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7471d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7472d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7473d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7474d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7475d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7476d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 74776ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7478d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7479d3d1a6afSToby Isaac 7480d3d1a6afSToby Isaac PetscFunctionBegin; 7481d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7482d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 74839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7484d3d1a6afSToby Isaac 74859566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7486d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7487d3d1a6afSToby Isaac if (aSec) { 74889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 74899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 74909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7491d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7492d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7493d3d1a6afSToby Isaac * into the global matrix anyway) */ 7494d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7495d3d1a6afSToby Isaac PetscInt b = points[p]; 74964b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7497d3d1a6afSToby Isaac 74989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7499ad540459SPierre Jolivet if (!bSecDof) continue; 750048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7501d3d1a6afSToby Isaac if (bDof) { 7502d3d1a6afSToby Isaac /* this point is constrained */ 7503d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7504d3d1a6afSToby Isaac PetscInt bOff, q; 7505d3d1a6afSToby Isaac 7506d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7507d3d1a6afSToby Isaac newNumPoints += bDof; 75089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7509d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7510d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7511d3d1a6afSToby Isaac PetscInt aDof; 7512d3d1a6afSToby Isaac 75139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7514d3d1a6afSToby Isaac newNumIndices += aDof; 7515d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7516d3d1a6afSToby Isaac PetscInt fDof; 7517d3d1a6afSToby Isaac 75189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7519d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7520d3d1a6afSToby Isaac } 7521d3d1a6afSToby Isaac } 75229371c9d4SSatish Balay } else { 7523d3d1a6afSToby Isaac /* this point is not constrained */ 7524d3d1a6afSToby Isaac newNumPoints++; 75254b2f2278SToby Isaac newNumIndices += bSecDof; 7526d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7527d3d1a6afSToby Isaac PetscInt fDof; 7528d3d1a6afSToby Isaac 75299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7530d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7531d3d1a6afSToby Isaac } 7532d3d1a6afSToby Isaac } 7533d3d1a6afSToby Isaac } 7534d3d1a6afSToby Isaac } 7535d3d1a6afSToby Isaac if (!anyConstrained) { 753672b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 753772b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 753872b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 753972b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 75409566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7542d3d1a6afSToby Isaac } 7543d3d1a6afSToby Isaac 75446ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 75456ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 75466ecaa68aSToby Isaac 7547f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7548d3d1a6afSToby Isaac 75496ecaa68aSToby Isaac if (!outPoints && !outValues) { 75506ecaa68aSToby Isaac if (offsets) { 7551ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 75526ecaa68aSToby Isaac } 75539566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75556ecaa68aSToby Isaac } 75566ecaa68aSToby Isaac 75571dca8a05SBarry Smith PetscCheck(!numFields || newOffsets[numFields] == newNumIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, newOffsets[numFields], newNumIndices); 7558d3d1a6afSToby Isaac 75599566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7560d3d1a6afSToby Isaac 7561d3d1a6afSToby Isaac /* workspaces */ 7562d3d1a6afSToby Isaac if (numFields) { 7563d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 75649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 75659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7566d3d1a6afSToby Isaac } 75679371c9d4SSatish Balay } else { 75689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 75699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7570d3d1a6afSToby Isaac } 7571d3d1a6afSToby Isaac 7572d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7573d3d1a6afSToby Isaac if (numFields) { 75744b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 75754b2f2278SToby Isaac 7576d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7577d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 75784b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7579d3d1a6afSToby Isaac 75809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75814b2f2278SToby Isaac if (!bSecDof) { 75824b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 75834b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 75844b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 75854b2f2278SToby Isaac } 75864b2f2278SToby Isaac continue; 75874b2f2278SToby Isaac } 758848a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7589d3d1a6afSToby Isaac if (bDof) { 7590d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7591d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7592d3d1a6afSToby Isaac 75939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 75949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7595d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7596d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7597d3d1a6afSToby Isaac PetscInt aFDof; 7598d3d1a6afSToby Isaac 75999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7600d3d1a6afSToby Isaac allFDof += aFDof; 7601d3d1a6afSToby Isaac } 7602d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7603d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7604d3d1a6afSToby Isaac } 76059371c9d4SSatish Balay } else { 7606d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7607d3d1a6afSToby Isaac PetscInt fDof; 7608d3d1a6afSToby Isaac 76099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7610d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7611d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7612d3d1a6afSToby Isaac } 7613d3d1a6afSToby Isaac } 7614d3d1a6afSToby Isaac } 76154b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 76164b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 76174b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7618d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7619d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7620d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7621d3d1a6afSToby Isaac } 762219f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 762319f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 76249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7625d3d1a6afSToby Isaac } 76269371c9d4SSatish Balay } else { 7627d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7628d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 76294b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7630d3d1a6afSToby Isaac 76319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 76324b2f2278SToby Isaac if (!bSecDof) { 76334b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 76344b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 76354b2f2278SToby Isaac continue; 76364b2f2278SToby Isaac } 763748a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7638d3d1a6afSToby Isaac if (bDof) { 76394b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7640d3d1a6afSToby Isaac 76419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7642d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7643d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7644d3d1a6afSToby Isaac 76459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7646d3d1a6afSToby Isaac allDof += aDof; 7647d3d1a6afSToby Isaac } 7648d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 76494b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 76509371c9d4SSatish Balay } else { 76514b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7652d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7653d3d1a6afSToby Isaac } 7654d3d1a6afSToby Isaac } 7655d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7656d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7657d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7658d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7659d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7660d3d1a6afSToby Isaac } 76619566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7662d3d1a6afSToby Isaac } 7663d3d1a6afSToby Isaac 76646ecaa68aSToby Isaac /* output arrays */ 76659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 76666ecaa68aSToby Isaac 7667d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 76689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 76699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 76709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 76719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7672d3d1a6afSToby Isaac if (numFields) { 7673d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7674d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7675d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 76764b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7677d3d1a6afSToby Isaac 76789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7679ad540459SPierre Jolivet if (!bSecDof) continue; 768048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7681d3d1a6afSToby Isaac if (bDof) { 7682d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7683d3d1a6afSToby Isaac 7684d3d1a6afSToby Isaac fStart[0] = 0; 7685d3d1a6afSToby Isaac fEnd[0] = 0; 7686d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7687d3d1a6afSToby Isaac PetscInt fDof; 7688d3d1a6afSToby Isaac 76899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7690d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7691d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7692d3d1a6afSToby Isaac } 76939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76949566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7695d3d1a6afSToby Isaac 7696d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7697d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7698d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7699d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7700d3d1a6afSToby Isaac 7701d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7702d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7703d3d1a6afSToby Isaac } 77049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7705d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7706d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7707d3d1a6afSToby Isaac 7708d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7709d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7710d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77129566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7713d3d1a6afSToby Isaac } 7714d3d1a6afSToby Isaac newP += bDof; 7715d3d1a6afSToby Isaac 77166ecaa68aSToby Isaac if (outValues) { 7717d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 771848a46eb9SPierre Jolivet for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p])); 7719d3d1a6afSToby Isaac } 77209371c9d4SSatish Balay } else { 7721d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7722d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7723d3d1a6afSToby Isaac newP++; 7724d3d1a6afSToby Isaac } 7725d3d1a6afSToby Isaac } 7726d3d1a6afSToby Isaac } else { 7727d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7728d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7729d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 77304b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7731d3d1a6afSToby Isaac 77329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7733ad540459SPierre Jolivet if (!bSecDof) continue; 773448a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7735d3d1a6afSToby Isaac if (bDof) { 7736d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7737d3d1a6afSToby Isaac 77389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 77399566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7740d3d1a6afSToby Isaac 77419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7742d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7743d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7744d3d1a6afSToby Isaac 7745d3d1a6afSToby Isaac /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 7746d3d1a6afSToby Isaac 7747d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7748d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77509566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7751d3d1a6afSToby Isaac } 7752d3d1a6afSToby Isaac newP += bDof; 7753d3d1a6afSToby Isaac 7754d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 775548a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 77569371c9d4SSatish Balay } else { 7757d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7758d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7759d3d1a6afSToby Isaac newP++; 7760d3d1a6afSToby Isaac } 7761d3d1a6afSToby Isaac } 7762d3d1a6afSToby Isaac } 7763d3d1a6afSToby Isaac 77646ecaa68aSToby Isaac if (outValues) { 77659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 77669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7767d3d1a6afSToby Isaac /* multiply constraints on the right */ 7768d3d1a6afSToby Isaac if (numFields) { 7769d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7770d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7771d3d1a6afSToby Isaac 7772d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7773d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7774d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7775d3d1a6afSToby Isaac PetscInt c, r, k; 7776d3d1a6afSToby Isaac PetscInt dof; 7777d3d1a6afSToby Isaac 77789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7779ad540459SPierre Jolivet if (!dof) continue; 7780d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7781d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7782d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7783d3d1a6afSToby Isaac 7784d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7785d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7786ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7787d3d1a6afSToby Isaac } 7788d3d1a6afSToby Isaac } 77899371c9d4SSatish Balay } else { 7790d3d1a6afSToby Isaac /* copy this column as is */ 7791d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7792ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7793d3d1a6afSToby Isaac } 7794d3d1a6afSToby Isaac } 7795d3d1a6afSToby Isaac oldOff += dof; 7796d3d1a6afSToby Isaac } 7797d3d1a6afSToby Isaac } 77989371c9d4SSatish Balay } else { 7799d3d1a6afSToby Isaac PetscInt oldOff = 0; 7800d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7801d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7802d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7803d3d1a6afSToby Isaac PetscInt c, r, k; 7804d3d1a6afSToby Isaac PetscInt dof; 7805d3d1a6afSToby Isaac 78069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7807ad540459SPierre Jolivet if (!dof) continue; 7808d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7809d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7810d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7811d3d1a6afSToby Isaac 7812d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7813d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7814ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7815d3d1a6afSToby Isaac } 7816d3d1a6afSToby Isaac } 78179371c9d4SSatish Balay } else { 7818d3d1a6afSToby Isaac /* copy this column as is */ 7819d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7820ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7821d3d1a6afSToby Isaac } 7822d3d1a6afSToby Isaac } 7823d3d1a6afSToby Isaac oldOff += dof; 7824d3d1a6afSToby Isaac } 7825d3d1a6afSToby Isaac } 7826d3d1a6afSToby Isaac 78276ecaa68aSToby Isaac if (multiplyLeft) { 78289566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 78299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7830d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7831d3d1a6afSToby Isaac if (numFields) { 7832d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7833d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7834d3d1a6afSToby Isaac 7835d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7836d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7837d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7838d3d1a6afSToby Isaac PetscInt c, r, k; 7839d3d1a6afSToby Isaac PetscInt dof; 7840d3d1a6afSToby Isaac 78419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7842d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7843d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7844d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7845d3d1a6afSToby Isaac 7846d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7847d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7848ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7849d3d1a6afSToby Isaac } 7850d3d1a6afSToby Isaac } 78519371c9d4SSatish Balay } else { 7852d3d1a6afSToby Isaac /* copy this row as is */ 7853d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7854ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7855d3d1a6afSToby Isaac } 7856d3d1a6afSToby Isaac } 7857d3d1a6afSToby Isaac oldOff += dof; 7858d3d1a6afSToby Isaac } 7859d3d1a6afSToby Isaac } 78609371c9d4SSatish Balay } else { 7861d3d1a6afSToby Isaac PetscInt oldOff = 0; 7862d3d1a6afSToby Isaac 7863d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7864d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7865d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7866d3d1a6afSToby Isaac PetscInt c, r, k; 7867d3d1a6afSToby Isaac PetscInt dof; 7868d3d1a6afSToby Isaac 78699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7870d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7871d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7872d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7873d3d1a6afSToby Isaac 7874d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7875d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7876ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7877d3d1a6afSToby Isaac } 7878d3d1a6afSToby Isaac } 78799371c9d4SSatish Balay } else { 7880d3d1a6afSToby Isaac /* copy this row as is */ 78819fc93327SToby Isaac for (r = 0; r < dof; r++) { 7882ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7883d3d1a6afSToby Isaac } 7884d3d1a6afSToby Isaac } 7885d3d1a6afSToby Isaac oldOff += dof; 7886d3d1a6afSToby Isaac } 7887d3d1a6afSToby Isaac } 7888d3d1a6afSToby Isaac 78899566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 78909371c9d4SSatish Balay } else { 78916ecaa68aSToby Isaac newValues = tmpValues; 78926ecaa68aSToby Isaac } 78936ecaa68aSToby Isaac } 78946ecaa68aSToby Isaac 7895d3d1a6afSToby Isaac /* clean up */ 78969566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 78979566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 78986ecaa68aSToby Isaac 7899d3d1a6afSToby Isaac if (numFields) { 7900d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 79019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 79029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 79039566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7904d3d1a6afSToby Isaac } 79059371c9d4SSatish Balay } else { 79069566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 79079566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 79089566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7909d3d1a6afSToby Isaac } 79109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7911d3d1a6afSToby Isaac 7912d3d1a6afSToby Isaac /* output */ 79136ecaa68aSToby Isaac if (outPoints) { 7914d3d1a6afSToby Isaac *outPoints = newPoints; 79159371c9d4SSatish Balay } else { 79169566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 79176ecaa68aSToby Isaac } 7918ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7919ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 79203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7921d3d1a6afSToby Isaac } 7922d3d1a6afSToby Isaac 79234a1e0b3eSMatthew G. Knepley /*@C 792471f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 79257cd05799SMatthew G. Knepley 79267cd05799SMatthew G. Knepley Not collective 79277cd05799SMatthew G. Knepley 79287cd05799SMatthew G. Knepley Input Parameters: 7929a1cb98faSBarry Smith + dm - The `DM` 7930a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7931a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 793271f0bbf9SMatthew G. Knepley . point - The point defining the closure 793371f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 79347cd05799SMatthew G. Knepley 793571f0bbf9SMatthew G. Knepley Output Parameters: 793671f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 793771f0bbf9SMatthew G. Knepley . indices - The dof indices 793820f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 793920f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 79407cd05799SMatthew G. Knepley 7941a1cb98faSBarry Smith Level: advanced 794236fa2b79SJed Brown 7943a1cb98faSBarry Smith Notes: 7944a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7945a1cb98faSBarry Smith 794620f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 794720f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 794836fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 794920f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 795036fa2b79SJed Brown indices (with the above semantics) are implied. 79517cd05799SMatthew G. Knepley 79521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7953a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 79544a1e0b3eSMatthew G. Knepley @*/ 7955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7956d71ae5a4SJacob Faibussowitsch { 795771f0bbf9SMatthew G. Knepley /* Closure ordering */ 79587773e69fSMatthew G. Knepley PetscSection clSection; 79597773e69fSMatthew G. Knepley IS clPoints; 796071f0bbf9SMatthew G. Knepley const PetscInt *clp; 796171f0bbf9SMatthew G. Knepley PetscInt *points; 796271f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 796371f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 79644acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 796571f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 796671f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 796771f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 796871f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 796971f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 797071f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 797171f0bbf9SMatthew G. Knepley 797271f0bbf9SMatthew G. Knepley PetscInt *idx; 797371f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 797471f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 79757773e69fSMatthew G. Knepley 797671f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 79777773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79787773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 797936fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 79804f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 79814f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 79824f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 79834f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 79849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 798563a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 79869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 798771f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 798807218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7989c459fbc1SJed Brown if (useClPerm) { 7990c459fbc1SJed Brown PetscInt depth, clsize; 79919566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7992c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7993c459fbc1SJed Brown PetscInt dof; 79949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7995c459fbc1SJed Brown clsize += dof; 7996c459fbc1SJed Brown } 79979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7998c459fbc1SJed Brown } 799971f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 800071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 80017773e69fSMatthew G. Knepley PetscInt dof, fdof; 80027773e69fSMatthew G. Knepley 80039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 80047773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 80059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 80067773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 80077773e69fSMatthew G. Knepley } 800871f0bbf9SMatthew G. Knepley Ni += dof; 80097773e69fSMatthew G. Knepley } 80107773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 80111dca8a05SBarry Smith PetscCheck(!Nf || offsets[Nf] == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[Nf], Ni); 801271f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 801371f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80149566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80159566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 801671f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 801771f0bbf9SMatthew G. Knepley if (values && flips[f]) { 801871f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 80196ecaa68aSToby Isaac 802071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 802171f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 802271f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 802371f0bbf9SMatthew G. Knepley 80249566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 80259566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 802671f0bbf9SMatthew G. Knepley if (flip) { 802771f0bbf9SMatthew G. Knepley PetscInt i, j, k; 802871f0bbf9SMatthew G. Knepley 802971f0bbf9SMatthew G. Knepley if (!valCopy) { 80309566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 803171f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 803271f0bbf9SMatthew G. Knepley *values = valCopy; 803371f0bbf9SMatthew G. Knepley } 803471f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 803571f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 803671f0bbf9SMatthew G. Knepley 803771f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 803871f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 803971f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 80406ecaa68aSToby Isaac } 80416ecaa68aSToby Isaac } 804271f0bbf9SMatthew G. Knepley } 804371f0bbf9SMatthew G. Knepley foffset += fdof; 804471f0bbf9SMatthew G. Knepley } 804571f0bbf9SMatthew G. Knepley } 804671f0bbf9SMatthew G. Knepley } 804771f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 80489566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 804971f0bbf9SMatthew G. Knepley if (NclC) { 80509566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 805171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80529566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80539566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 805471f0bbf9SMatthew G. Knepley } 805571f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80569566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 80579566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 805871f0bbf9SMatthew G. Knepley } 80599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 806071f0bbf9SMatthew G. Knepley Ncl = NclC; 806171f0bbf9SMatthew G. Knepley Ni = NiC; 806271f0bbf9SMatthew G. Knepley points = pointsC; 806371f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 806471f0bbf9SMatthew G. Knepley } 806571f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 80669566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 806771f0bbf9SMatthew G. Knepley if (Nf) { 806871f0bbf9SMatthew G. Knepley PetscInt idxOff; 806971f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 807071f0bbf9SMatthew G. Knepley 80719371c9d4SSatish Balay if (outOffsets) { 80729371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 80739371c9d4SSatish Balay } 80749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 807571f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 807671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 807771f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 807871f0bbf9SMatthew G. Knepley 80799566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 80807773e69fSMatthew G. Knepley } 80817773e69fSMatthew G. Knepley } else { 808271f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 808371f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 808471f0bbf9SMatthew G. Knepley 80859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 808671f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 808771f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 808871f0bbf9SMatthew G. Knepley * global section. */ 80899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 809071f0bbf9SMatthew G. Knepley } 809171f0bbf9SMatthew G. Knepley } 809271f0bbf9SMatthew G. Knepley } else { 809371f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 809471f0bbf9SMatthew G. Knepley 809571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 809671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 80974acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 80984acb8e1eSToby Isaac 80999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 810071f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 810171f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 81029566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 81037773e69fSMatthew G. Knepley } 81047773e69fSMatthew G. Knepley } 810571f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 810671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 81079566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 81089566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 81094acb8e1eSToby Isaac } 811071f0bbf9SMatthew G. Knepley if (NclC) { 81119566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 81127773e69fSMatthew G. Knepley } else { 81139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 81147773e69fSMatthew G. Knepley } 811571f0bbf9SMatthew G. Knepley 811671f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 811771f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 81183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81197773e69fSMatthew G. Knepley } 81207773e69fSMatthew G. Knepley 81217cd05799SMatthew G. Knepley /*@C 812271f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 81237cd05799SMatthew G. Knepley 81247cd05799SMatthew G. Knepley Not collective 81257cd05799SMatthew G. Knepley 81267cd05799SMatthew G. Knepley Input Parameters: 8127a1cb98faSBarry Smith + dm - The `DM` 8128a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8129a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 813071f0bbf9SMatthew G. Knepley . point - The point defining the closure 813171f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 813271f0bbf9SMatthew G. Knepley 813371f0bbf9SMatthew G. Knepley Output Parameters: 813471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 813571f0bbf9SMatthew G. Knepley . indices - The dof indices 813620f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 813720f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 813871f0bbf9SMatthew G. Knepley 8139a1cb98faSBarry Smith Level: advanced 814071f0bbf9SMatthew G. Knepley 8141a1cb98faSBarry Smith Notes: 8142a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8143a1cb98faSBarry Smith 8144a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 814571f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 814671f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 814771f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 814871f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 81497cd05799SMatthew G. Knepley 81501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 81517cd05799SMatthew G. Knepley @*/ 8152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8153d71ae5a4SJacob Faibussowitsch { 81547773e69fSMatthew G. Knepley PetscFunctionBegin; 81557773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81564f572ea9SToby Isaac PetscAssertPointer(indices, 7); 81579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 81583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81597773e69fSMatthew G. Knepley } 81607773e69fSMatthew G. Knepley 8161e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8162d71ae5a4SJacob Faibussowitsch { 8163552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8164552f7358SJed Brown PetscInt *indices; 816571f0bbf9SMatthew G. Knepley PetscInt numIndices; 816671f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8167552f7358SJed Brown PetscErrorCode ierr; 8168552f7358SJed Brown 8169552f7358SJed Brown PetscFunctionBegin; 8170552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81719566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 81723dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 81739566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 81743dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8175e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8176552f7358SJed Brown 8177e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81780d644c17SKarl Rupp 81799566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8180d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81814a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8182552f7358SJed Brown if (ierr) { 8183552f7358SJed Brown PetscMPIInt rank; 8184552f7358SJed Brown 81859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81869566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81879566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81899566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8190c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8191552f7358SJed Brown } 81924a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81934a1e0b3eSMatthew G. Knepley PetscInt i; 81949566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 819563a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81969566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81974a1e0b3eSMatthew G. Knepley } 819871f0bbf9SMatthew G. Knepley 81999566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 82009566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 82013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82024acb8e1eSToby Isaac } 820371f0bbf9SMatthew G. Knepley 82044a1e0b3eSMatthew G. Knepley /*@C 8205e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8206e8e188d2SZach Atkins 8207e8e188d2SZach Atkins Not collective 8208e8e188d2SZach Atkins 8209e8e188d2SZach Atkins Input Parameters: 8210e8e188d2SZach Atkins + dm - The `DM` 8211e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8212e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8213e8e188d2SZach Atkins . A - The matrix 8214e8e188d2SZach Atkins . point - The point in the `DM` 8215e8e188d2SZach Atkins . values - The array of values 8216e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8217e8e188d2SZach Atkins 8218e8e188d2SZach Atkins Level: intermediate 8219e8e188d2SZach Atkins 8220e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8221e8e188d2SZach Atkins @*/ 8222e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8223e8e188d2SZach Atkins { 8224e8e188d2SZach Atkins PetscFunctionBegin; 8225e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8226e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8227e8e188d2SZach Atkins } 8228e8e188d2SZach Atkins 8229e8e188d2SZach Atkins /*@C 823060225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 82314a1e0b3eSMatthew G. Knepley 82324a1e0b3eSMatthew G. Knepley Not collective 82334a1e0b3eSMatthew G. Knepley 82344a1e0b3eSMatthew G. Knepley Input Parameters: 8235a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 823620f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8237e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 823820f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8239a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 824020f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8241e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 824220f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 82434a1e0b3eSMatthew G. Knepley . A - The matrix 8244a1cb98faSBarry Smith . point - The point in the `DM` 82454a1e0b3eSMatthew G. Knepley . values - The array of values 8246a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 82474a1e0b3eSMatthew G. Knepley 82484a1e0b3eSMatthew G. Knepley Level: intermediate 82494a1e0b3eSMatthew G. Knepley 82501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 82514a1e0b3eSMatthew G. Knepley @*/ 8252e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, PetscBool useRowPerm, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, PetscBool useColPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8253d71ae5a4SJacob Faibussowitsch { 825471f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 825571f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 825671f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 825771f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 825871f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 825971f0bbf9SMatthew G. Knepley 826071f0bbf9SMatthew G. Knepley PetscFunctionBegin; 826171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 82629566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 826371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 82649566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 826571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8266e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 82679566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8268e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 82699566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8270e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8271e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 827271f0bbf9SMatthew G. Knepley 8273e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8274e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 827571f0bbf9SMatthew G. Knepley 82769566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 8277d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 82784a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 827971f0bbf9SMatthew G. Knepley if (ierr) { 828071f0bbf9SMatthew G. Knepley PetscMPIInt rank; 828171f0bbf9SMatthew G. Knepley 82829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82839566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82849566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82859566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 82869566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 82879566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 8288d3d1a6afSToby Isaac } 828971f0bbf9SMatthew G. Knepley 8290e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8291e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 82929566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 82933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8294552f7358SJed Brown } 8295552f7358SJed Brown 8296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8297d71ae5a4SJacob Faibussowitsch { 8298de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8299de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8300de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8301de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 830217c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8303de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8304412e9a14SMatthew G. Knepley DMPolytopeType ct; 83054ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8306de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8307de41b84cSMatthew G. Knepley 8308de41b84cSMatthew G. Knepley PetscFunctionBegin; 8309de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8310de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83119566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8312de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 83139566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8314de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 83159566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8316de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 83179566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8318de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8319de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 83209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 832163a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 83229566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 83239566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8324de41b84cSMatthew G. Knepley /* Column indices */ 83259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83264ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8327de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8328de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 83299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8330de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8331de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8332de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8333de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8334de41b84cSMatthew G. Knepley ++q; 8335de41b84cSMatthew G. Knepley } 8336de41b84cSMatthew G. Knepley } 8337de41b84cSMatthew G. Knepley numCPoints = q; 8338de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8339de41b84cSMatthew G. Knepley PetscInt fdof; 8340de41b84cSMatthew G. Knepley 83419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 83424ca5e9f5SMatthew G. Knepley if (!dof) continue; 8343de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8345de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8346de41b84cSMatthew G. Knepley } 8347de41b84cSMatthew G. Knepley numCIndices += dof; 8348de41b84cSMatthew G. Knepley } 8349de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8350de41b84cSMatthew G. Knepley /* Row indices */ 83519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8352412e9a14SMatthew G. Knepley { 8353012bc364SMatthew G. Knepley DMPlexTransform tr; 8354012bc364SMatthew G. Knepley DMPolytopeType *rct; 8355012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8356012bc364SMatthew G. Knepley 83579566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 83589566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 83599566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8360012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 83619566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8362412e9a14SMatthew G. Knepley } 83639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8364de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8365de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 83669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8367de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 83689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8369de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8370de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 83719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 83724ca5e9f5SMatthew G. Knepley if (!dof) continue; 83739371c9d4SSatish Balay for (s = 0; s < q; ++s) 83749371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 83754ca5e9f5SMatthew G. Knepley if (s < q) continue; 8376de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8377de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8378de41b84cSMatthew G. Knepley ++q; 8379de41b84cSMatthew G. Knepley } 8380de41b84cSMatthew G. Knepley } 83819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8382de41b84cSMatthew G. Knepley } 8383de41b84cSMatthew G. Knepley numFPoints = q; 8384de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8385de41b84cSMatthew G. Knepley PetscInt fdof; 8386de41b84cSMatthew G. Knepley 83879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83884ca5e9f5SMatthew G. Knepley if (!dof) continue; 8389de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8391de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8392de41b84cSMatthew G. Knepley } 8393de41b84cSMatthew G. Knepley numFIndices += dof; 8394de41b84cSMatthew G. Knepley } 8395de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8396de41b84cSMatthew G. Knepley 83971dca8a05SBarry Smith PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices); 83981dca8a05SBarry Smith PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices); 83999566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84009566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8401de41b84cSMatthew G. Knepley if (numFields) { 84024acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84034acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84044acb8e1eSToby Isaac 84054acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8408de41b84cSMatthew G. Knepley } 84094acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84124acb8e1eSToby Isaac } 84134acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84164acb8e1eSToby Isaac } 84174acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84189566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84199566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8420de41b84cSMatthew G. Knepley } 8421de41b84cSMatthew G. Knepley } else { 84224acb8e1eSToby Isaac const PetscInt **permsF = NULL; 84234acb8e1eSToby Isaac const PetscInt **permsC = NULL; 84244acb8e1eSToby Isaac 84259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84274acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 84284acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 84294acb8e1eSToby Isaac 84309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84319566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8432de41b84cSMatthew G. Knepley } 84334acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 84344acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 84354acb8e1eSToby Isaac 84369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84379566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8438de41b84cSMatthew G. Knepley } 84399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84409566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8441de41b84cSMatthew G. Knepley } 84429566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84434acb8e1eSToby Isaac /* TODO: flips */ 8444d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8445de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8446de41b84cSMatthew G. Knepley if (ierr) { 8447de41b84cSMatthew G. Knepley PetscMPIInt rank; 8448de41b84cSMatthew G. Knepley 84499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 84509566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 84519566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84539566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8454de41b84cSMatthew G. Knepley } 84559566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 84569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84589566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 84593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8460de41b84cSMatthew G. Knepley } 8461de41b84cSMatthew G. Knepley 8462d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8463d71ae5a4SJacob Faibussowitsch { 84647c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 84657c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8466230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 846717c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8468412e9a14SMatthew G. Knepley DMPolytopeType ct; 84697c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 84707c927364SMatthew G. Knepley 84717c927364SMatthew G. Knepley PetscFunctionBegin; 84727c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 84737c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 84749566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 84757c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84769566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84777c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84789566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84797c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84809566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84817c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 848363a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84847c927364SMatthew G. Knepley /* Column indices */ 84859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84867c927364SMatthew G. Knepley maxFPoints = numCPoints; 84877c927364SMatthew G. Knepley /* Compress out points not in the section */ 84887c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84907c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84917c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84927c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84937c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84947c927364SMatthew G. Knepley ++q; 84957c927364SMatthew G. Knepley } 84967c927364SMatthew G. Knepley } 84977c927364SMatthew G. Knepley numCPoints = q; 84987c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84997c927364SMatthew G. Knepley PetscInt fdof; 85007c927364SMatthew G. Knepley 85019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 85027c927364SMatthew G. Knepley if (!dof) continue; 85037c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 85057c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 85067c927364SMatthew G. Knepley } 85077c927364SMatthew G. Knepley numCIndices += dof; 85087c927364SMatthew G. Knepley } 85097c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 85107c927364SMatthew G. Knepley /* Row indices */ 85119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8512412e9a14SMatthew G. Knepley { 8513012bc364SMatthew G. Knepley DMPlexTransform tr; 8514012bc364SMatthew G. Knepley DMPolytopeType *rct; 8515012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8516012bc364SMatthew G. Knepley 85179566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 85189566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 85199566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8520012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 85219566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8522412e9a14SMatthew G. Knepley } 85239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 85247c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 85257c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 85269566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 85277c927364SMatthew G. Knepley /* Compress out points not in the section */ 85289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 85297c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 85307c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 85319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 85327c927364SMatthew G. Knepley if (!dof) continue; 85339371c9d4SSatish Balay for (s = 0; s < q; ++s) 85349371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 85357c927364SMatthew G. Knepley if (s < q) continue; 85367c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 85377c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 85387c927364SMatthew G. Knepley ++q; 85397c927364SMatthew G. Knepley } 85407c927364SMatthew G. Knepley } 85419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 85427c927364SMatthew G. Knepley } 85437c927364SMatthew G. Knepley numFPoints = q; 85447c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 85457c927364SMatthew G. Knepley PetscInt fdof; 85467c927364SMatthew G. Knepley 85479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 85487c927364SMatthew G. Knepley if (!dof) continue; 85497c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 85517c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 85527c927364SMatthew G. Knepley } 85537c927364SMatthew G. Knepley numFIndices += dof; 85547c927364SMatthew G. Knepley } 85557c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 85567c927364SMatthew G. Knepley 85571dca8a05SBarry Smith PetscCheck(!numFields || foffsets[numFields] == numFIndices, PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices); 85581dca8a05SBarry Smith PetscCheck(!numFields || coffsets[numFields] == numCIndices, PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices); 85597c927364SMatthew G. Knepley if (numFields) { 85604acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 85614acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 85624acb8e1eSToby Isaac 85634acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85667c927364SMatthew G. Knepley } 85674acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 85689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85699566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 85704acb8e1eSToby Isaac } 85714acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 85729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85739566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 85744acb8e1eSToby Isaac } 85754acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85769566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85779566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85787c927364SMatthew G. Knepley } 85797c927364SMatthew G. Knepley } else { 85804acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85814acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85824acb8e1eSToby Isaac 85839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85854acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85864acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85874acb8e1eSToby Isaac 85889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85899566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85907c927364SMatthew G. Knepley } 85914acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85924acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85934acb8e1eSToby Isaac 85949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85967c927364SMatthew G. Knepley } 85979566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85989566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85997c927364SMatthew G. Knepley } 86009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 86019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 86023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86037c927364SMatthew G. Knepley } 86047c927364SMatthew G. Knepley 86057cd05799SMatthew G. Knepley /*@C 86067cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 86077cd05799SMatthew G. Knepley 86087cd05799SMatthew G. Knepley Input Parameter: 8609a1cb98faSBarry Smith . dm - The `DMPLEX` object 86107cd05799SMatthew G. Knepley 86117cd05799SMatthew G. Knepley Output Parameter: 86127cd05799SMatthew G. Knepley . cellHeight - The height of a cell 86137cd05799SMatthew G. Knepley 86147cd05799SMatthew G. Knepley Level: developer 86157cd05799SMatthew G. Knepley 86161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 86177cd05799SMatthew G. Knepley @*/ 8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8619d71ae5a4SJacob Faibussowitsch { 8620552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8621552f7358SJed Brown 8622552f7358SJed Brown PetscFunctionBegin; 8623552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86244f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8625552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 86263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8627552f7358SJed Brown } 8628552f7358SJed Brown 86297cd05799SMatthew G. Knepley /*@C 86307cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 86317cd05799SMatthew G. Knepley 86327cd05799SMatthew G. Knepley Input Parameters: 8633a1cb98faSBarry Smith + dm - The `DMPLEX` object 86347cd05799SMatthew G. Knepley - cellHeight - The height of a cell 86357cd05799SMatthew G. Knepley 86367cd05799SMatthew G. Knepley Level: developer 86377cd05799SMatthew G. Knepley 86381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 86397cd05799SMatthew G. Knepley @*/ 8640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8641d71ae5a4SJacob Faibussowitsch { 8642552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8643552f7358SJed Brown 8644552f7358SJed Brown PetscFunctionBegin; 8645552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8646552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 86473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8648552f7358SJed Brown } 8649552f7358SJed Brown 8650e6139122SMatthew G. Knepley /*@ 86512827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8652e6139122SMatthew G. Knepley 86532827ebadSStefano Zampini Input Parameters: 86542827ebadSStefano Zampini + dm - The `DMPLEX` object 86552827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8656e6139122SMatthew G. Knepley 8657e6139122SMatthew G. Knepley Output Parameters: 86582827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 86592827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8660e6139122SMatthew G. Knepley 86612a9f31c0SMatthew G. Knepley Level: advanced 8662e6139122SMatthew G. Knepley 86632827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8664e6139122SMatthew G. Knepley @*/ 86652827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8666d71ae5a4SJacob Faibussowitsch { 86672827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 86682827ebadSStefano Zampini DMLabel label; 86692827ebadSStefano Zampini PetscInt pStart, pEnd; 8670e6139122SMatthew G. Knepley 8671e6139122SMatthew G. Knepley PetscFunctionBegin; 8672e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86732827ebadSStefano Zampini if (start) { 86744f572ea9SToby Isaac PetscAssertPointer(start, 3); 86752827ebadSStefano Zampini *start = 0; 86762827ebadSStefano Zampini } 86772827ebadSStefano Zampini if (end) { 86784f572ea9SToby Isaac PetscAssertPointer(end, 4); 86792827ebadSStefano Zampini *end = 0; 86802827ebadSStefano Zampini } 86812827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86822827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86832827ebadSStefano Zampini if (mesh->tr) { 86842827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86852827ebadSStefano Zampini } else { 86862827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86872827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86882827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86892827ebadSStefano Zampini } 86903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8691e6139122SMatthew G. Knepley } 8692e6139122SMatthew G. Knepley 8693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8694d71ae5a4SJacob Faibussowitsch { 8695552f7358SJed Brown PetscSection section, globalSection; 8696552f7358SJed Brown PetscInt *numbers, p; 8697552f7358SJed Brown 8698552f7358SJed Brown PetscFunctionBegin; 8699d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 87009566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 87019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 870248a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 87039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8704eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 87059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8706552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 87079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8708ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8709ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8710552f7358SJed Brown } 87119566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8712ef48cebcSMatthew G. Knepley if (globalSize) { 8713ef48cebcSMatthew G. Knepley PetscLayout layout; 87149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 87159566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 87169566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8717ef48cebcSMatthew G. Knepley } 87189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 87199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 87203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8721552f7358SJed Brown } 8722552f7358SJed Brown 8723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8724d71ae5a4SJacob Faibussowitsch { 8725412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8726552f7358SJed Brown 8727552f7358SJed Brown PetscFunctionBegin; 87289566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87299566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 87309566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 87319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 87323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8733552f7358SJed Brown } 873481ed3555SMatthew G. Knepley 87358dab3259SMatthew G. Knepley /*@ 87367cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 87377cd05799SMatthew G. Knepley 87387cd05799SMatthew G. Knepley Input Parameter: 8739a1cb98faSBarry Smith . dm - The `DMPLEX` object 87407cd05799SMatthew G. Knepley 87417cd05799SMatthew G. Knepley Output Parameter: 87427cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 87437cd05799SMatthew G. Knepley 87447cd05799SMatthew G. Knepley Level: developer 87457cd05799SMatthew G. Knepley 87461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 87477cd05799SMatthew G. Knepley @*/ 8748d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8749d71ae5a4SJacob Faibussowitsch { 875081ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 875181ed3555SMatthew G. Knepley 875281ed3555SMatthew G. Knepley PetscFunctionBegin; 875381ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87549566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8755552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 87563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8757552f7358SJed Brown } 8758552f7358SJed Brown 8759d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8760d71ae5a4SJacob Faibussowitsch { 8761412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 876281ed3555SMatthew G. Knepley 876381ed3555SMatthew G. Knepley PetscFunctionBegin; 876481ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 87669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 87673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 876881ed3555SMatthew G. Knepley } 876981ed3555SMatthew G. Knepley 87708dab3259SMatthew G. Knepley /*@ 87716aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 87727cd05799SMatthew G. Knepley 87737cd05799SMatthew G. Knepley Input Parameter: 8774a1cb98faSBarry Smith . dm - The `DMPLEX` object 87757cd05799SMatthew G. Knepley 87767cd05799SMatthew G. Knepley Output Parameter: 87777cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87787cd05799SMatthew G. Knepley 87797cd05799SMatthew G. Knepley Level: developer 87807cd05799SMatthew G. Knepley 87811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87827cd05799SMatthew G. Knepley @*/ 8783d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8784d71ae5a4SJacob Faibussowitsch { 8785552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8786552f7358SJed Brown 8787552f7358SJed Brown PetscFunctionBegin; 8788552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87899566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8790552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8792552f7358SJed Brown } 8793552f7358SJed Brown 87948dab3259SMatthew G. Knepley /*@ 8795966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8796966484cfSJed Brown 879720f4b53cSBarry Smith Collective 87987cd05799SMatthew G. Knepley 87997cd05799SMatthew G. Knepley Input Parameter: 8800a1cb98faSBarry Smith . dm - The `DMPLEX` object 88017cd05799SMatthew G. Knepley 88027cd05799SMatthew G. Knepley Output Parameter: 88037cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 88047cd05799SMatthew G. Knepley 8805a1cb98faSBarry Smith Level: developer 8806966484cfSJed Brown 8807a1cb98faSBarry Smith Notes: 8808a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8809966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8810966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8811966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8812966484cfSJed Brown 8813966484cfSJed Brown The partitioned mesh is 8814966484cfSJed Brown ``` 8815966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8816966484cfSJed Brown ``` 8817966484cfSJed Brown and its global numbering is 8818966484cfSJed Brown ``` 8819966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8820966484cfSJed Brown ``` 8821966484cfSJed Brown Then the global numbering is provided as 8822966484cfSJed Brown ``` 8823966484cfSJed Brown [0] Number of indices in set 5 8824966484cfSJed Brown [0] 0 0 8825966484cfSJed Brown [0] 1 1 8826966484cfSJed Brown [0] 2 3 8827966484cfSJed Brown [0] 3 4 8828966484cfSJed Brown [0] 4 -6 8829966484cfSJed Brown [1] Number of indices in set 3 8830966484cfSJed Brown [1] 0 2 8831966484cfSJed Brown [1] 1 5 8832966484cfSJed Brown [1] 2 6 8833966484cfSJed Brown ``` 8834966484cfSJed Brown 88351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 88367cd05799SMatthew G. Knepley @*/ 8837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8838d71ae5a4SJacob Faibussowitsch { 8839ef48cebcSMatthew G. Knepley IS nums[4]; 8840862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8841ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 88420c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8843ef48cebcSMatthew G. Knepley 8844ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8845ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 88470c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 88489566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 88490c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8850862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8851862913ffSStefano Zampini PetscInt end; 8852862913ffSStefano Zampini 8853862913ffSStefano Zampini depths[d] = depth - d; 88549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 88550c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8856862913ffSStefano Zampini } 88570c15888dSMatthew G. Knepley if (empty) 88580c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 88590c15888dSMatthew G. Knepley depths[d] = -1; 88600c15888dSMatthew G. Knepley starts[d] = -1; 88610c15888dSMatthew G. Knepley } 88620c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 88631c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8864ad540459SPierre Jolivet for (d = 0; d <= depth; ++d) PetscCheck(starts[d] < 0 || depths[d] == gdepths[d], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT, depths[d], gdepths[d]); 88650c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8866ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8867ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8868ef48cebcSMatthew G. Knepley 88699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 88709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8871ef48cebcSMatthew G. Knepley shift += gsize; 8872ef48cebcSMatthew G. Knepley } 8873d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 88749566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8876ef48cebcSMatthew G. Knepley } 8877ef48cebcSMatthew G. Knepley 887808a22f4bSMatthew G. Knepley /*@ 887908a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 888008a22f4bSMatthew G. Knepley 888108a22f4bSMatthew G. Knepley Input Parameter: 8882a1cb98faSBarry Smith . dm - The `DMPLEX` object 888308a22f4bSMatthew G. Knepley 888408a22f4bSMatthew G. Knepley Output Parameter: 888508a22f4bSMatthew G. Knepley . ranks - The rank field 888608a22f4bSMatthew G. Knepley 8887a1cb98faSBarry Smith Options Database Key: 888820f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 888908a22f4bSMatthew G. Knepley 889008a22f4bSMatthew G. Knepley Level: intermediate 889108a22f4bSMatthew G. Knepley 88921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 889308a22f4bSMatthew G. Knepley @*/ 8894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8895d71ae5a4SJacob Faibussowitsch { 889608a22f4bSMatthew G. Knepley DM rdm; 889708a22f4bSMatthew G. Knepley PetscFE fe; 889808a22f4bSMatthew G. Knepley PetscScalar *r; 889908a22f4bSMatthew G. Knepley PetscMPIInt rank; 8900a55f9a55SMatthew G. Knepley DMPolytopeType ct; 890108a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8902a55f9a55SMatthew G. Knepley PetscBool simplex; 890308a22f4bSMatthew G. Knepley 890408a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8905f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89064f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 89079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 89089566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 89099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 89109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 89119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8912a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 89139566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 89149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 89159566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89169566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89179566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89189566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 89199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 89209566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 892108a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 892208a22f4bSMatthew G. Knepley PetscScalar *lr; 892308a22f4bSMatthew G. Knepley 89249566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 892571f09efeSPierre Jolivet if (lr) *lr = rank; 892608a22f4bSMatthew G. Knepley } 89279566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 89289566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 893008a22f4bSMatthew G. Knepley } 893108a22f4bSMatthew G. Knepley 8932ca8062c8SMatthew G. Knepley /*@ 8933acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 893418e14f0cSMatthew G. Knepley 893518e14f0cSMatthew G. Knepley Input Parameters: 893620f4b53cSBarry Smith + dm - The `DMPLEX` 893720f4b53cSBarry Smith - label - The `DMLabel` 893818e14f0cSMatthew G. Knepley 893918e14f0cSMatthew G. Knepley Output Parameter: 894018e14f0cSMatthew G. Knepley . val - The label value field 894118e14f0cSMatthew G. Knepley 894220f4b53cSBarry Smith Options Database Key: 894320f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 894418e14f0cSMatthew G. Knepley 894518e14f0cSMatthew G. Knepley Level: intermediate 894618e14f0cSMatthew G. Knepley 89471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 894818e14f0cSMatthew G. Knepley @*/ 8949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8950d71ae5a4SJacob Faibussowitsch { 89511033741fSStefano Zampini DM rdm, plex; 8952acf3173eSStefano Zampini Vec lval; 8953acf3173eSStefano Zampini PetscSection section; 895418e14f0cSMatthew G. Knepley PetscFE fe; 895518e14f0cSMatthew G. Knepley PetscScalar *v; 8956acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 8957acf3173eSStefano Zampini DMPolytopeType ct; 8958acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 8959acf3173eSStefano Zampini const char *lname, *prefix; 896018e14f0cSMatthew G. Knepley 896118e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 896218e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89634f572ea9SToby Isaac PetscAssertPointer(label, 2); 89644f572ea9SToby Isaac PetscAssertPointer(val, 3); 89659566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 8966acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 8967acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 8968acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 8969acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 89709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 8971acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 8972acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 8973acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 8974acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 8975acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 89769566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89779566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89789566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89799566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 8980acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 8981acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 8982acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 8983acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 8984acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 8985acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 8986acf3173eSStefano Zampini PetscInt cval, dof, off; 898718e14f0cSMatthew G. Knepley 8988acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 8989acf3173eSStefano Zampini if (!dof) continue; 8990acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 8991acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 8992acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 899318e14f0cSMatthew G. Knepley } 8994acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 8995acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 8996acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 89979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 899918e14f0cSMatthew G. Knepley } 900018e14f0cSMatthew G. Knepley 900118e14f0cSMatthew G. Knepley /*@ 9002ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 9003ca8062c8SMatthew G. Knepley 900469916449SMatthew G. Knepley Input Parameter: 9005a1cb98faSBarry Smith . dm - The `DMPLEX` object 9006a1cb98faSBarry Smith 9007a1cb98faSBarry Smith Level: developer 9008ca8062c8SMatthew G. Knepley 900995eb5ee5SVaclav Hapla Notes: 901095eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 901195eb5ee5SVaclav Hapla 901220f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9013ca8062c8SMatthew G. Knepley 90141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9015ca8062c8SMatthew G. Knepley @*/ 9016d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 9017d71ae5a4SJacob Faibussowitsch { 9018ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 9019ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 9020ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 902157beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 902257beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9023ca8062c8SMatthew G. Knepley 9024ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9025ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90269566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 90279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 90289566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9029ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 90309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9031ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 90329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 90339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9034ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 903542e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 903642e66dfaSMatthew G. Knepley PetscInt d; 903742e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 90389371c9d4SSatish Balay if (cone[c] == cone[d]) { 90399371c9d4SSatish Balay dup = PETSC_TRUE; 90409371c9d4SSatish Balay break; 90419371c9d4SSatish Balay } 904242e66dfaSMatthew G. Knepley } 90439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 90449566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9045ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9046ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9047ca8062c8SMatthew G. Knepley } 904842e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 904963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 905048a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 90519566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 905263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 905348a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 90549566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 905563a3b9bcSJacob Faibussowitsch PetscCheck(!dup, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not repeatedly found in support of repeated cone point %" PetscInt_FMT, p, cone[c]); 9056f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9057ca8062c8SMatthew G. Knepley } 905842e66dfaSMatthew G. Knepley } 90599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 90609371c9d4SSatish Balay if (p != pp) { 90619371c9d4SSatish Balay storagecheck = PETSC_FALSE; 90629371c9d4SSatish Balay continue; 90639371c9d4SSatish Balay } 90649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 90659566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9066ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 90679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 90689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9069ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 90709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 90719371c9d4SSatish Balay if (cone[c] != pp) { 90729371c9d4SSatish Balay c = 0; 90739371c9d4SSatish Balay break; 90749371c9d4SSatish Balay } 9075ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9076ca8062c8SMatthew G. Knepley } 9077ca8062c8SMatthew G. Knepley if (c >= coneSize) { 907863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 907948a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 90809566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 908163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 908248a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 90839566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 908463a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9085ca8062c8SMatthew G. Knepley } 9086ca8062c8SMatthew G. Knepley } 9087ca8062c8SMatthew G. Knepley } 908857beb4faSStefano Zampini if (storagecheck) { 90899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 90909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 909163a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 909257beb4faSStefano Zampini } 90933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9094ca8062c8SMatthew G. Knepley } 9095ca8062c8SMatthew G. Knepley 9096412e9a14SMatthew G. Knepley /* 9097412e9a14SMatthew G. Knepley For submeshes with cohesive cells (see DMPlexConstructCohesiveCells()), we allow a special case where some of the boundary of a face (edges and vertices) are not duplicated. We call these special boundary points "unsplit", since the same edge or vertex appears in both copies of the face. These unsplit points throw off our counting, so we have to explicitly account for them here. 9098412e9a14SMatthew G. Knepley */ 9099d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9100d71ae5a4SJacob Faibussowitsch { 9101412e9a14SMatthew G. Knepley DMPolytopeType cct; 9102412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9103412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9104412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9105412e9a14SMatthew G. Knepley 9106412e9a14SMatthew G. Knepley PetscFunctionBegin; 9107412e9a14SMatthew G. Knepley *unsplit = 0; 9108412e9a14SMatthew G. Knepley switch (ct) { 9109d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9110d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9111d71ae5a4SJacob Faibussowitsch break; 9112412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 91139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9115412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 91169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9117412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9118412e9a14SMatthew G. Knepley } 9119412e9a14SMatthew G. Knepley break; 9120412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9121412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 91229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9124412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 91259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 91269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9127412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 91289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9129412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9130412e9a14SMatthew G. Knepley PetscInt p; 91319371c9d4SSatish Balay for (p = 0; p < npt; ++p) 91329371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9133412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9134412e9a14SMatthew G. Knepley } 9135412e9a14SMatthew G. Knepley } 9136412e9a14SMatthew G. Knepley } 9137412e9a14SMatthew G. Knepley break; 9138d71ae5a4SJacob Faibussowitsch default: 9139d71ae5a4SJacob Faibussowitsch break; 9140412e9a14SMatthew G. Knepley } 9141412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 91429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9143412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9144412e9a14SMatthew G. Knepley } 91453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9146412e9a14SMatthew G. Knepley } 9147412e9a14SMatthew G. Knepley 9148ca8062c8SMatthew G. Knepley /*@ 9149ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9150ca8062c8SMatthew G. Knepley 9151ca8062c8SMatthew G. Knepley Input Parameters: 9152a1cb98faSBarry Smith + dm - The `DMPLEX` object 915358723a97SMatthew G. Knepley - cellHeight - Normally 0 9154ca8062c8SMatthew G. Knepley 9155a1cb98faSBarry Smith Level: developer 9156a1cb98faSBarry Smith 915795eb5ee5SVaclav Hapla Notes: 915895eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 915925c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9160ca8062c8SMatthew G. Knepley 916120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 916295eb5ee5SVaclav Hapla 91631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9164ca8062c8SMatthew G. Knepley @*/ 9165d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9166d71ae5a4SJacob Faibussowitsch { 9167412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9168412e9a14SMatthew G. Knepley DMPolytopeType ct; 9169412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9170ca8062c8SMatthew G. Knepley 9171ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9172ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91739566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 91749566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 91759566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9176412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9177412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9178412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 917958723a97SMatthew G. Knepley 91809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 918163a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9182412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9183412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 91849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 918563a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == DMPolytopeTypeGetConeSize(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has cone size %" PetscInt_FMT " != %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct)); 9186412e9a14SMatthew G. Knepley } 91879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 918858723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 918958723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9190412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 919158723a97SMatthew G. Knepley } 91929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9193412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9194412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9195412e9a14SMatthew G. Knepley PetscInt unsplit; 919642363296SMatthew G. Knepley 91979566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9198412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 919942363296SMatthew G. Knepley } 920063a3b9bcSJacob Faibussowitsch PetscCheck(Nv == DMPolytopeTypeGetNumVertices(ct), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices != %" PetscInt_FMT, c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct)); 920142363296SMatthew G. Knepley } 92023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9203ca8062c8SMatthew G. Knepley } 92049bf0dad6SMatthew G. Knepley 92059bf0dad6SMatthew G. Knepley /*@ 92069bf0dad6SMatthew G. Knepley DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 92079bf0dad6SMatthew G. Knepley 920820f4b53cSBarry Smith Collective 9209899ea2b8SJacob Faibussowitsch 92109bf0dad6SMatthew G. Knepley Input Parameters: 9211a1cb98faSBarry Smith + dm - The `DMPLEX` object 92129bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 92139bf0dad6SMatthew G. Knepley 9214a1cb98faSBarry Smith Level: developer 9215a1cb98faSBarry Smith 921645da879fSVaclav Hapla Notes: 921745da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 921845da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 921945da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 922045da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 92219bf0dad6SMatthew G. Knepley 9222a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 922395eb5ee5SVaclav Hapla 92241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 92259bf0dad6SMatthew G. Knepley @*/ 9226d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9227d71ae5a4SJacob Faibussowitsch { 9228ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9229899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 92309bf0dad6SMatthew G. Knepley 92319bf0dad6SMatthew G. Knepley PetscFunctionBegin; 92329bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92338f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 92343ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 92358f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 92363ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 92373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9238899ea2b8SJacob Faibussowitsch } 9239899ea2b8SJacob Faibussowitsch 92409566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 92429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9243ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 92449566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 92453554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9246412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9247412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9248ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9249412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9250412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 92519bf0dad6SMatthew G. Knepley 92529566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 92539566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9254412e9a14SMatthew G. Knepley if (unsplit) continue; 92559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 92569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 92579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 92589566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92599bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 92609bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 92619bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 92629bf0dad6SMatthew G. Knepley } 92639566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 926463a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == numFaces, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " faces but should have %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, numFaces); 92659bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9266d4961f80SStefano Zampini DMPolytopeType fct; 92679bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 92689bf0dad6SMatthew G. Knepley 92699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 92709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 92719bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 92729bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 92739bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 92749bf0dad6SMatthew G. Knepley } 927563a3b9bcSJacob Faibussowitsch PetscCheck(fnumCorners == faceSizes[f], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices but should have %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]); 92769bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9277b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9278b5a892a1SMatthew G. Knepley PetscInt v1; 9279b5a892a1SMatthew G. Knepley 92809566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 928163a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 92829566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 928363a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 92849566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 928563a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ", ornt %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s vertex %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff + v]); 9286b5a892a1SMatthew G. Knepley } 92879bf0dad6SMatthew G. Knepley } 92889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9289412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 92909bf0dad6SMatthew G. Knepley } 92919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92939bf0dad6SMatthew G. Knepley } 92943554e41dSMatthew G. Knepley } 92953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9296552f7358SJed Brown } 92973913d7c8SMatthew G. Knepley 9298bb6a34a8SMatthew G. Knepley /*@ 9299bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9300bb6a34a8SMatthew G. Knepley 9301bb6a34a8SMatthew G. Knepley Input Parameter: 9302a1cb98faSBarry Smith . dm - The `DMPLEX` object 9303a1cb98faSBarry Smith 9304a1cb98faSBarry Smith Level: developer 9305bb6a34a8SMatthew G. Knepley 930695eb5ee5SVaclav Hapla Notes: 930795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 930895eb5ee5SVaclav Hapla 930920f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9310bb6a34a8SMatthew G. Knepley 93111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9312bb6a34a8SMatthew G. Knepley @*/ 9313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9314d71ae5a4SJacob Faibussowitsch { 9315a2a9e04cSMatthew G. Knepley Vec coordinates; 9316bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9317bb6a34a8SMatthew G. Knepley PetscReal vol; 931851a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9319bb6a34a8SMatthew G. Knepley 9320bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 93219566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 93229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 93233ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 93249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9325bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 93269566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9327a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 93289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 93293ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9330412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9331412e9a14SMatthew G. Knepley DMPolytopeType ct; 9332412e9a14SMatthew G. Knepley PetscInt unsplit; 9333412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9334412e9a14SMatthew G. Knepley 93359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9336412e9a14SMatthew G. Knepley switch (ct) { 9337412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9338412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9339d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9340d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9341d71ae5a4SJacob Faibussowitsch break; 9342d71ae5a4SJacob Faibussowitsch default: 9343d71ae5a4SJacob Faibussowitsch break; 9344412e9a14SMatthew G. Knepley } 9345412e9a14SMatthew G. Knepley switch (ct) { 9346412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9347412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9348412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9349d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9350d71ae5a4SJacob Faibussowitsch continue; 9351d71ae5a4SJacob Faibussowitsch default: 9352d71ae5a4SJacob Faibussowitsch break; 9353412e9a14SMatthew G. Knepley } 93549566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9355412e9a14SMatthew G. Knepley if (unsplit) continue; 93569566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 93571dca8a05SBarry Smith PetscCheck(detJ >= -PETSC_SMALL && (detJ > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double)detJ); 935863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 93596858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 93606858538eSMatthew G. Knepley if (depth > 1) { 93619566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 93621dca8a05SBarry Smith PetscCheck(vol >= -PETSC_SMALL && (vol > 0.0 || ignoreZeroVol), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double)vol); 936363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9364bb6a34a8SMatthew G. Knepley } 9365bb6a34a8SMatthew G. Knepley } 93663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9367bb6a34a8SMatthew G. Knepley } 9368bb6a34a8SMatthew G. Knepley 936903da9461SVaclav Hapla /*@ 937020f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 93717726db96SVaclav Hapla 937220f4b53cSBarry Smith Collective 937303da9461SVaclav Hapla 937403da9461SVaclav Hapla Input Parameters: 9375a1cb98faSBarry Smith + dm - The `DMPLEX` object 937620f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9377a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9378a1cb98faSBarry Smith 9379a1cb98faSBarry Smith Level: developer 938003da9461SVaclav Hapla 9381e83a0d2dSVaclav Hapla Notes: 9382e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 938303da9461SVaclav Hapla 9384a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 938595eb5ee5SVaclav Hapla 9386baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9387d7d32a9aSMatthew G. Knepley 93881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 938903da9461SVaclav Hapla @*/ 9390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9391d71ae5a4SJacob Faibussowitsch { 93927726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93937726db96SVaclav Hapla const PetscInt *locals; 93947726db96SVaclav Hapla const PetscSFNode *remotes; 9395f0cfc026SVaclav Hapla PetscBool distributed; 93967726db96SVaclav Hapla MPI_Comm comm; 93977726db96SVaclav Hapla PetscMPIInt rank; 939803da9461SVaclav Hapla 939903da9461SVaclav Hapla PetscFunctionBegin; 940003da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94017726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 94027726db96SVaclav Hapla else pointSF = dm->sf; 94037726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 94047726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 94057726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94067726db96SVaclav Hapla { 94077726db96SVaclav Hapla PetscMPIInt mpiFlag; 94087726db96SVaclav Hapla 94097726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 94107726db96SVaclav Hapla PetscCheck(mpiFlag == MPI_CONGRUENT || mpiFlag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "DM and Point SF have different communicators (flag %d)", mpiFlag); 94117726db96SVaclav Hapla } 94127726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 94139566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 94147726db96SVaclav Hapla if (!distributed) { 94157726db96SVaclav Hapla PetscCheck(nroots < 0 || nleaves == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Undistributed DMPlex cannot have non-empty PointSF (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 94163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 94178918e3e2SVaclav Hapla } 94187726db96SVaclav Hapla PetscCheck(nroots >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves); 94197726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 942003da9461SVaclav Hapla 94217726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 94227726db96SVaclav Hapla { 94237726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 94247726db96SVaclav Hapla 94257726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 94267726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9427d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 94287726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 94297726db96SVaclav Hapla } 94307726db96SVaclav Hapla 94317726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 94327726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 94337726db96SVaclav Hapla PetscAssert(remotes[l].rank != (PetscInt)rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index); 94347726db96SVaclav Hapla } 94357726db96SVaclav Hapla 94367726db96SVaclav Hapla /* Check there are no cells in interface */ 94377726db96SVaclav Hapla if (!overlap) { 94387726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 94397726db96SVaclav Hapla 94409566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94419566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9442f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94437726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9444f5869d18SMatthew G. Knepley 94457726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 94467726db96SVaclav Hapla } 944703da9461SVaclav Hapla } 9448ece87651SVaclav Hapla 94497726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 94507726db96SVaclav Hapla { 94517726db96SVaclav Hapla const PetscInt *rootdegree; 94527726db96SVaclav Hapla 94537726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 94547726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9455f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94567726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9457f5869d18SMatthew G. Knepley const PetscInt *cone; 9458f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9459f5869d18SMatthew G. Knepley 94609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 94619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9462f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9463f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 94647726db96SVaclav Hapla if (locals) { 94659566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 94667726db96SVaclav Hapla } else { 94677726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 94687726db96SVaclav Hapla } 946963a3b9bcSJacob Faibussowitsch PetscCheck(idx >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " but not %" PetscInt_FMT " from its cone", point, cone[c]); 9470f5869d18SMatthew G. Knepley } 9471f5869d18SMatthew G. Knepley } 9472ece87651SVaclav Hapla } 94737726db96SVaclav Hapla } 94743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 947503da9461SVaclav Hapla } 947603da9461SVaclav Hapla 94777f9d8d6cSVaclav Hapla /*@ 947820f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 94797f9d8d6cSVaclav Hapla 94807f9d8d6cSVaclav Hapla Input Parameter: 9481a1cb98faSBarry Smith . dm - The `DMPLEX` object 9482a1cb98faSBarry Smith 9483a1cb98faSBarry Smith Level: developer 94847f9d8d6cSVaclav Hapla 94857f9d8d6cSVaclav Hapla Notes: 94867f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 94877f9d8d6cSVaclav Hapla 948820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 94897f9d8d6cSVaclav Hapla 949020f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94917f9d8d6cSVaclav Hapla 94921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94937f9d8d6cSVaclav Hapla @*/ 9494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9495d71ae5a4SJacob Faibussowitsch { 94967f9d8d6cSVaclav Hapla PetscInt cellHeight; 94977f9d8d6cSVaclav Hapla 9498b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94997f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95009566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 95019566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 95029566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 95039566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9504d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 95059566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 95063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9507b5a892a1SMatthew G. Knepley } 9508b5a892a1SMatthew G. Knepley 95099371c9d4SSatish Balay typedef struct cell_stats { 9510068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9511068a5610SStefano Zampini PetscInt count; 9512068a5610SStefano Zampini } cell_stats_t; 9513068a5610SStefano Zampini 9514d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9515d71ae5a4SJacob Faibussowitsch { 9516068a5610SStefano Zampini PetscInt i, N = *len; 9517068a5610SStefano Zampini 9518068a5610SStefano Zampini for (i = 0; i < N; i++) { 9519068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9520068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9521068a5610SStefano Zampini 9522068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9523068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9524068a5610SStefano Zampini B->sum += A->sum; 9525068a5610SStefano Zampini B->squaresum += A->squaresum; 9526068a5610SStefano Zampini B->count += A->count; 9527068a5610SStefano Zampini } 9528068a5610SStefano Zampini } 9529068a5610SStefano Zampini 9530068a5610SStefano Zampini /*@ 953143fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9532068a5610SStefano Zampini 953320f4b53cSBarry Smith Collective 95348261a58bSMatthew G. Knepley 9535068a5610SStefano Zampini Input Parameters: 9536a1cb98faSBarry Smith + dm - The `DMPLEX` object 953720f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9538a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9539a1cb98faSBarry Smith 9540a1cb98faSBarry Smith Level: developer 9541068a5610SStefano Zampini 954295eb5ee5SVaclav Hapla Notes: 954395eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 954495eb5ee5SVaclav Hapla 9545a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9546068a5610SStefano Zampini 95471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9548068a5610SStefano Zampini @*/ 9549d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9550d71ae5a4SJacob Faibussowitsch { 9551068a5610SStefano Zampini DM dmCoarse; 955243fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 955343fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 955443fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 955543fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9556412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 955743fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9558068a5610SStefano Zampini 9559068a5610SStefano Zampini PetscFunctionBegin; 9560068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9561068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9562068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9563068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9564068a5610SStefano Zampini stats.count = 0; 9565068a5610SStefano Zampini 95669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 95679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 95689566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 95699566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 95709566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 95719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9572412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9573068a5610SStefano Zampini PetscInt i; 9574068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9575068a5610SStefano Zampini 95769566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 957763a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 957843fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9579068a5610SStefano Zampini frobJ += J[i] * J[i]; 9580068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9581068a5610SStefano Zampini } 9582068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9583068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9584068a5610SStefano Zampini 9585068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9586068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9587068a5610SStefano Zampini stats.sum += cond; 9588068a5610SStefano Zampini stats.squaresum += cond2; 9589068a5610SStefano Zampini stats.count++; 95908261a58bSMatthew G. Knepley if (output && cond > limit) { 959143fa8764SMatthew G. Knepley PetscSection coordSection; 959243fa8764SMatthew G. Knepley Vec coordsLocal; 959343fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 959443fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 959543fa8764SMatthew G. Knepley 95969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95989566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 959963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 960043fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 960163a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 960243fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 96039566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 96049566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 960543fa8764SMatthew G. Knepley } 96069566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 960743fa8764SMatthew G. Knepley } 96089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 960943fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 961043fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 961143fa8764SMatthew G. Knepley 961243fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 961343fa8764SMatthew G. Knepley PetscReal len; 961443fa8764SMatthew G. Knepley 96159566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 961663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 961743fa8764SMatthew G. Knepley } 961843fa8764SMatthew G. Knepley } 96199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 96209566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 962143fa8764SMatthew G. Knepley } 9622068a5610SStefano Zampini } 96239566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9624068a5610SStefano Zampini 9625068a5610SStefano Zampini if (size > 1) { 9626068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9627068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9628068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9629068a5610SStefano Zampini MPI_Op statReduce; 9630068a5610SStefano Zampini 96319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 96329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 96339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 96349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 96359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 96369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9637068a5610SStefano Zampini } else { 96389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9639068a5610SStefano Zampini } 9640dd400576SPatrick Sanan if (rank == 0) { 9641068a5610SStefano Zampini count = globalStats.count; 9642068a5610SStefano Zampini min = globalStats.min; 9643068a5610SStefano Zampini max = globalStats.max; 9644068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9645068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9646068a5610SStefano Zampini } 9647068a5610SStefano Zampini 964848a46eb9SPierre Jolivet if (output) PetscCall(PetscPrintf(comm, "Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double)min, (double)max, (double)mean, (double)stdev)); 96499566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9650068a5610SStefano Zampini 96519566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9652068a5610SStefano Zampini if (dmCoarse) { 9653068a5610SStefano Zampini PetscBool isplex; 9654068a5610SStefano Zampini 96559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 96561baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9657068a5610SStefano Zampini } 96583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9659068a5610SStefano Zampini } 9660068a5610SStefano Zampini 9661f108dbd7SJacob Faibussowitsch /*@ 9662f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9663f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9664f108dbd7SJacob Faibussowitsch 966520f4b53cSBarry Smith Collective 9666f108dbd7SJacob Faibussowitsch 9667f108dbd7SJacob Faibussowitsch Input Parameters: 9668a1cb98faSBarry Smith + dm - The `DMPLEX` object 9669a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9670f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9671f108dbd7SJacob Faibussowitsch 9672f108dbd7SJacob Faibussowitsch Output Parameters: 967320f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9674a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9675f108dbd7SJacob Faibussowitsch 9676f108dbd7SJacob Faibussowitsch Options Database Keys: 9677a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9678f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9679f108dbd7SJacob Faibussowitsch 9680a1cb98faSBarry Smith Level: intermediate 9681a1cb98faSBarry Smith 9682f108dbd7SJacob Faibussowitsch Notes: 9683a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9684f108dbd7SJacob Faibussowitsch 9685a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9686f108dbd7SJacob Faibussowitsch 9687f108dbd7SJacob Faibussowitsch Where A_i is the i'th face-normal vector, f_i is the vector from the cell centroid to the i'th face centroid, and c_i 9688f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9689f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9690f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9691f108dbd7SJacob Faibussowitsch 9692f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9693f108dbd7SJacob Faibussowitsch 9694a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9695f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9696f108dbd7SJacob Faibussowitsch 9697f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9698f108dbd7SJacob Faibussowitsch 96991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9700f108dbd7SJacob Faibussowitsch @*/ 9701d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9702d71ae5a4SJacob Faibussowitsch { 97036ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 97046ed19f2fSJacob Faibussowitsch PetscInt *idx; 97056ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9706f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 97076ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9708f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9709f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9710f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9711f108dbd7SJacob Faibussowitsch IS glob; 9712f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9713f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9714f108dbd7SJacob Faibussowitsch 9715f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9716f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9717ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 97184f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 97196bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 97209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 97219566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 972263a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 97236ed19f2fSJacob Faibussowitsch { 97246ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 97256ed19f2fSJacob Faibussowitsch 97269566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9727f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9728f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9729f108dbd7SJacob Faibussowitsch 97309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 973198921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9732f108dbd7SJacob Faibussowitsch } 97336ed19f2fSJacob Faibussowitsch } 9734f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97354f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 97369566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 97379566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 97389371c9d4SSatish Balay } else { 97399371c9d4SSatish Balay *OrthQualLabel = NULL; 97409371c9d4SSatish Balay } 97419566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97429566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 97439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 97449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 97459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 97469566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 97479566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 97489566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 97499566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 97509566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 97519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 97529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 97539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 97549566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 97559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 97569566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 97579566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 97589566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 97596ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 97606ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9761f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9762f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9763898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9764f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9765f108dbd7SJacob Faibussowitsch 97666ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9767f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9768f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 97699566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 97709566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9771f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 97729566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 97736ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 97746ed19f2fSJacob Faibussowitsch PetscInt i; 97756ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9776f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9777f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9778f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9779f108dbd7SJacob Faibussowitsch 9780f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9781f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 97829566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9783f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 97846ed19f2fSJacob Faibussowitsch { 97856ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 97866ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 97876ed19f2fSJacob Faibussowitsch 97889566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97899566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 97909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97916ed19f2fSJacob Faibussowitsch } 9792f108dbd7SJacob Faibussowitsch 9793f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9794f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9795f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9796f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9797f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9798addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9799addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9800addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9801f108dbd7SJacob Faibussowitsch } 9802addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9803addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9804addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9805f108dbd7SJacob Faibussowitsch 9806f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9807f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9808f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9809f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9810f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9811f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9812f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9813f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9814f108dbd7SJacob Faibussowitsch } 9815ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9816ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9817f108dbd7SJacob Faibussowitsch } 98189566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 98199566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9820f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 98216ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9822f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98239566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9824f108dbd7SJacob Faibussowitsch } 9825f108dbd7SJacob Faibussowitsch } 98269566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 98279566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 98289566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 98299566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 98309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 98319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9832f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98339566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9834f108dbd7SJacob Faibussowitsch } 98359566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9836cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 98379566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 98383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9839f108dbd7SJacob Faibussowitsch } 9840f108dbd7SJacob Faibussowitsch 9841d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 98421eb70e55SToby Isaac * interpolator construction */ 9843d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9844d71ae5a4SJacob Faibussowitsch { 98451eb70e55SToby Isaac PetscSection section, newSection, gsection; 98461eb70e55SToby Isaac PetscSF sf; 98471eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 98481eb70e55SToby Isaac 98491eb70e55SToby Isaac PetscFunctionBegin; 98501eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98514f572ea9SToby Isaac PetscAssertPointer(odm, 2); 98529566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 98539566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9854712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 98551eb70e55SToby Isaac if (!ghasConstraints) { 98569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 98571eb70e55SToby Isaac *odm = dm; 98583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98591eb70e55SToby Isaac } 98609566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 98619566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 98629566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 98639566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 9864eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 98659566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 98669566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 98673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98681eb70e55SToby Isaac } 98691eb70e55SToby Isaac 9870d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9871d71ae5a4SJacob Faibussowitsch { 98721eb70e55SToby Isaac DM dmco, dmfo; 98731eb70e55SToby Isaac Mat interpo; 98741eb70e55SToby Isaac Vec rscale; 98751eb70e55SToby Isaac Vec cglobalo, clocal; 98761eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 98771eb70e55SToby Isaac PetscBool regular; 98781eb70e55SToby Isaac 98791eb70e55SToby Isaac PetscFunctionBegin; 98809566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 98819566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 98829566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 98839566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 98849566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 98859566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 98869566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 98879566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 98889566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 98899566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 98909566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98919566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98929566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98939566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98949566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98959566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98969566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98979566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98989566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98999566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 99009566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 99019566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 99029566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 99039566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 99041eb70e55SToby Isaac *shift = fglobal; 99059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 99069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 99079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 99089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 99099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 99109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 99119566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 99129566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 99133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99141eb70e55SToby Isaac } 99151eb70e55SToby Isaac 9916d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9917d71ae5a4SJacob Faibussowitsch { 99181eb70e55SToby Isaac PetscObject shifto; 99191eb70e55SToby Isaac Vec shift; 99201eb70e55SToby Isaac 99211eb70e55SToby Isaac PetscFunctionBegin; 99221eb70e55SToby Isaac if (!interp) { 99231eb70e55SToby Isaac Vec rscale; 99241eb70e55SToby Isaac 99259566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 99269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 99271eb70e55SToby Isaac } else { 99289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 99291eb70e55SToby Isaac } 99309566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 99311eb70e55SToby Isaac if (!shifto) { 99329566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 99339566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 99341eb70e55SToby Isaac shifto = (PetscObject)shift; 99359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 99361eb70e55SToby Isaac } 99371eb70e55SToby Isaac shift = (Vec)shifto; 99389566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 99399566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 99409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 99413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99421eb70e55SToby Isaac } 99431eb70e55SToby Isaac 9944bceba477SMatthew G. Knepley /* Pointwise interpolation 9945bceba477SMatthew G. Knepley Just code FEM for now 9946bceba477SMatthew G. Knepley u^f = I u^c 99474ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 99484ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 99494ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9950bceba477SMatthew G. Knepley */ 9951d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9952d71ae5a4SJacob Faibussowitsch { 9953bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9954bceba477SMatthew G. Knepley PetscInt m, n; 9955a063dac3SMatthew G. Knepley void *ctx; 995668132eb9SMatthew G. Knepley DM cdm; 9957cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9958bceba477SMatthew G. Knepley 9959bceba477SMatthew G. Knepley PetscFunctionBegin; 99609566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 99619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 99629566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 99639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 996468132eb9SMatthew G. Knepley 99659566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 99669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 99679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 99689566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 99699566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 997068132eb9SMatthew G. Knepley 99719566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99729566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99739566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 99749566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 99759566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 99764db47ee9SStefano Zampini if (scaling) { 99775d1c2e58SMatthew G. Knepley /* Use naive scaling */ 99789566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 99794db47ee9SStefano Zampini } 99803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9981a063dac3SMatthew G. Knepley } 9982bceba477SMatthew G. Knepley 9983d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9984d71ae5a4SJacob Faibussowitsch { 99856dbf9973SLawrence Mitchell VecScatter ctx; 998690748bafSMatthew G. Knepley 9987a063dac3SMatthew G. Knepley PetscFunctionBegin; 99889566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 99899566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 99909566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9992bceba477SMatthew G. Knepley } 9993bceba477SMatthew G. Knepley 9994d71ae5a4SJacob Faibussowitsch static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 9995d71ae5a4SJacob Faibussowitsch { 999600635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 999700635df3SMatthew G. Knepley PetscInt c; 999800635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99993e9753d6SMatthew G. Knepley } 100003e9753d6SMatthew G. Knepley 10001d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 10002d71ae5a4SJacob Faibussowitsch { 10003b4937a87SMatthew G. Knepley DM dmc; 10004b4937a87SMatthew G. Knepley PetscDS ds; 10005b4937a87SMatthew G. Knepley Vec ones, locmass; 10006b4937a87SMatthew G. Knepley IS cellIS; 10007b4937a87SMatthew G. Knepley PetscFormKey key; 10008b4937a87SMatthew G. Knepley PetscInt depth; 10009b4937a87SMatthew G. Knepley 10010b4937a87SMatthew G. Knepley PetscFunctionBegin; 100119566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 100129566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 100139566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 100149566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 100159566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 100169566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 100179566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 100189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 100199566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 100209566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 100219566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10022b4937a87SMatthew G. Knepley key.label = NULL; 10023b4937a87SMatthew G. Knepley key.value = 0; 10024b4937a87SMatthew G. Knepley key.field = 0; 10025b4937a87SMatthew G. Knepley key.part = 0; 100269566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 100279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100289566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 100299566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 100309566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 100319566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 100329566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 100339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10035b4937a87SMatthew G. Knepley } 10036b4937a87SMatthew G. Knepley 10037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10038d71ae5a4SJacob Faibussowitsch { 10039bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10040bd041c0cSMatthew G. Knepley PetscInt m, n; 10041bd041c0cSMatthew G. Knepley void *ctx; 10042bd041c0cSMatthew G. Knepley DM cdm; 10043bd041c0cSMatthew G. Knepley PetscBool regular; 10044bd041c0cSMatthew G. Knepley 10045bd041c0cSMatthew G. Knepley PetscFunctionBegin; 100463e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 100473e9753d6SMatthew G. Knepley DM dmc; 100483e9753d6SMatthew G. Knepley PetscDS ds; 10049b4937a87SMatthew G. Knepley PetscWeakForm wf; 100503e9753d6SMatthew G. Knepley Vec u; 100513e9753d6SMatthew G. Knepley IS cellIS; 1005206ad1575SMatthew G. Knepley PetscFormKey key; 100533e9753d6SMatthew G. Knepley PetscInt depth; 100543e9753d6SMatthew G. Knepley 100559566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 100569566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 100579566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 100589566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 100599566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 100609566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 100619566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 100628d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 100639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 100649566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 100659566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 100666528b96dSMatthew G. Knepley key.label = NULL; 100676528b96dSMatthew G. Knepley key.value = 0; 100686528b96dSMatthew G. Knepley key.field = 0; 1006906ad1575SMatthew G. Knepley key.part = 0; 100709566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 100719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100728d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 100739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100743e9753d6SMatthew G. Knepley } else { 100759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 100769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 100779566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 100789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10079bd041c0cSMatthew G. Knepley 100809566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 100819566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 100829566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 100839566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10084bd041c0cSMatthew G. Knepley 100859566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 100869566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 100879566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 100889566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 100893e9753d6SMatthew G. Knepley } 100909566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10092bd041c0cSMatthew G. Knepley } 10093bd041c0cSMatthew G. Knepley 100940aef6b92SMatthew G. Knepley /*@ 100950aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100960aef6b92SMatthew G. Knepley 100970aef6b92SMatthew G. Knepley Input Parameter: 10098a1cb98faSBarry Smith . dm - The `DMPLEX` object 100990aef6b92SMatthew G. Knepley 101000aef6b92SMatthew G. Knepley Output Parameter: 101010aef6b92SMatthew G. Knepley . regular - The flag 101020aef6b92SMatthew G. Knepley 101030aef6b92SMatthew G. Knepley Level: intermediate 101040aef6b92SMatthew G. Knepley 101051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 101060aef6b92SMatthew G. Knepley @*/ 10107d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10108d71ae5a4SJacob Faibussowitsch { 101090aef6b92SMatthew G. Knepley PetscFunctionBegin; 101100aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101114f572ea9SToby Isaac PetscAssertPointer(regular, 2); 101120aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 101133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101140aef6b92SMatthew G. Knepley } 101150aef6b92SMatthew G. Knepley 101160aef6b92SMatthew G. Knepley /*@ 101170aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 101180aef6b92SMatthew G. Knepley 101190aef6b92SMatthew G. Knepley Input Parameters: 10120a1cb98faSBarry Smith + dm - The `DMPLEX` object 101210aef6b92SMatthew G. Knepley - regular - The flag 101220aef6b92SMatthew G. Knepley 101230aef6b92SMatthew G. Knepley Level: intermediate 101240aef6b92SMatthew G. Knepley 101251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 101260aef6b92SMatthew G. Knepley @*/ 10127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10128d71ae5a4SJacob Faibussowitsch { 101290aef6b92SMatthew G. Knepley PetscFunctionBegin; 101300aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101310aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 101323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101330aef6b92SMatthew G. Knepley } 101340aef6b92SMatthew G. Knepley 10135a68b90caSToby Isaac /*@ 10136f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10137a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10138a68b90caSToby Isaac 10139a1cb98faSBarry Smith Not Collective 10140a68b90caSToby Isaac 10141f899ff85SJose E. Roman Input Parameter: 10142a1cb98faSBarry Smith . dm - The `DMPLEX` object 10143a68b90caSToby Isaac 10144a68b90caSToby Isaac Output Parameters: 1014520f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1014620f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10147a68b90caSToby Isaac 10148a68b90caSToby Isaac Level: intermediate 10149a68b90caSToby Isaac 101501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10151a68b90caSToby Isaac @*/ 10152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10153d71ae5a4SJacob Faibussowitsch { 10154a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10155a68b90caSToby Isaac 10156a68b90caSToby Isaac PetscFunctionBegin; 10157a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101589566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10159a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10160a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 101613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10162a68b90caSToby Isaac } 10163a68b90caSToby Isaac 10164a68b90caSToby Isaac /*@ 10165a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10166a68b90caSToby Isaac 1016720f4b53cSBarry Smith Collective 10168a68b90caSToby Isaac 10169a68b90caSToby Isaac Input Parameters: 10170a1cb98faSBarry Smith + dm - The `DMPLEX` object 10171a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10172a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10173a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10174a68b90caSToby Isaac 10175a68b90caSToby Isaac Level: intermediate 10176a68b90caSToby Isaac 10177a1cb98faSBarry Smith Notes: 10178a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10179a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10180a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10181a4e35b19SJacob Faibussowitsch 10182a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10183a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10184a1cb98faSBarry Smith 1018520f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10186a1cb98faSBarry Smith 101871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10188a68b90caSToby Isaac @*/ 10189d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10190d71ae5a4SJacob Faibussowitsch { 10191a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10192e228b242SToby Isaac PetscMPIInt result; 10193a68b90caSToby Isaac 10194a68b90caSToby Isaac PetscFunctionBegin; 10195a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10196e228b242SToby Isaac if (anchorSection) { 10197e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101991dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10200e228b242SToby Isaac } 10201e228b242SToby Isaac if (anchorIS) { 10202e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 102039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 102041dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10205e228b242SToby Isaac } 10206a68b90caSToby Isaac 102079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 102089566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10209a68b90caSToby Isaac plex->anchorSection = anchorSection; 10210a68b90caSToby Isaac 102119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 102129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10213a68b90caSToby Isaac plex->anchorIS = anchorIS; 10214a68b90caSToby Isaac 10215cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10216a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10217a68b90caSToby Isaac const PetscInt *anchors; 10218a68b90caSToby Isaac 102199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 102209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 102219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10222a68b90caSToby Isaac for (a = 0; a < size; a++) { 10223a68b90caSToby Isaac PetscInt p; 10224a68b90caSToby Isaac 10225a68b90caSToby Isaac p = anchors[a]; 10226a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10227a68b90caSToby Isaac PetscInt dof; 10228a68b90caSToby Isaac 102299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10230a68b90caSToby Isaac if (dof) { 102319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1023263a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10233a68b90caSToby Isaac } 10234a68b90caSToby Isaac } 10235a68b90caSToby Isaac } 102369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10237a68b90caSToby Isaac } 10238f7c74593SToby Isaac /* reset the generic constraints */ 102399566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 102403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10241a68b90caSToby Isaac } 10242a68b90caSToby Isaac 10243d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10244d71ae5a4SJacob Faibussowitsch { 10245f7c74593SToby Isaac PetscSection anchorSection; 102466995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10247a68b90caSToby Isaac 10248a68b90caSToby Isaac PetscFunctionBegin; 10249a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102509566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 102519566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 102529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102536995de1eSToby Isaac if (numFields) { 10254719ab38cSToby Isaac PetscInt f; 102559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10256719ab38cSToby Isaac 10257719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10258719ab38cSToby Isaac PetscInt numComp; 10259719ab38cSToby Isaac 102609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 102619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10262719ab38cSToby Isaac } 102636995de1eSToby Isaac } 102649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 102659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102666995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 102676995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 102686995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 102699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10270a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 102719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10272a68b90caSToby Isaac if (dof) { 102739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 102749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10275a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 102769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 102779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10278a68b90caSToby Isaac } 10279a68b90caSToby Isaac } 10280a68b90caSToby Isaac } 102819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 102829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 102833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10284a68b90caSToby Isaac } 10285a68b90caSToby Isaac 10286d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10287d71ae5a4SJacob Faibussowitsch { 10288f7c74593SToby Isaac PetscSection aSec; 10289ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 102900ac89760SToby Isaac const PetscInt *anchors; 102910ac89760SToby Isaac PetscInt numFields, f; 1029266ad2231SToby Isaac IS aIS; 10293e19f7ee6SMark Adams MatType mtype; 10294e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102950ac89760SToby Isaac 102960ac89760SToby Isaac PetscFunctionBegin; 102970ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 103009566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 103019566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 103029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 103039566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 103049566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 103059566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10306e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10307e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10308e19f7ee6SMark Adams else mtype = MATSEQAIJ; 103099566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 103109566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 103119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 103126995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 103139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 103149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 103159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 103160ac89760SToby Isaac i[0] = 0; 103179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 103180ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10319f19733c5SToby Isaac PetscInt rDof, rOff, r; 10320f19733c5SToby Isaac 103219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10322f19733c5SToby Isaac if (!rDof) continue; 103239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103240ac89760SToby Isaac if (numFields) { 103250ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103260ac89760SToby Isaac annz = 0; 10327f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10328f19733c5SToby Isaac a = anchors[rOff + r]; 10329ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103310ac89760SToby Isaac annz += aDof; 103320ac89760SToby Isaac } 103339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10335ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103360ac89760SToby Isaac } 103372f7452b8SBarry Smith } else { 103380ac89760SToby Isaac annz = 0; 103399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103400ac89760SToby Isaac for (q = 0; q < dof; q++) { 10341ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10342ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103440ac89760SToby Isaac annz += aDof; 103450ac89760SToby Isaac } 103469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10348ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103490ac89760SToby Isaac } 103500ac89760SToby Isaac } 103510ac89760SToby Isaac nnz = i[m]; 103529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 103530ac89760SToby Isaac offset = 0; 103540ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 103550ac89760SToby Isaac if (numFields) { 103560ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103580ac89760SToby Isaac for (q = 0; q < dof; q++) { 103590ac89760SToby Isaac PetscInt rDof, rOff, r; 103609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103620ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103630ac89760SToby Isaac PetscInt s; 103640ac89760SToby Isaac 103650ac89760SToby Isaac a = anchors[rOff + r]; 10366ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10369ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103700ac89760SToby Isaac } 103710ac89760SToby Isaac } 103720ac89760SToby Isaac } 103732f7452b8SBarry Smith } else { 103749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103750ac89760SToby Isaac for (q = 0; q < dof; q++) { 103760ac89760SToby Isaac PetscInt rDof, rOff, r; 103779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103790ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103800ac89760SToby Isaac PetscInt s; 103810ac89760SToby Isaac 103820ac89760SToby Isaac a = anchors[rOff + r]; 10383ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10386ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103870ac89760SToby Isaac } 103880ac89760SToby Isaac } 103890ac89760SToby Isaac } 103900ac89760SToby Isaac } 103919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103929566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103939566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103960ac89760SToby Isaac } 103970ac89760SToby Isaac 10398d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10399d71ae5a4SJacob Faibussowitsch { 10400f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10401f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1040266ad2231SToby Isaac Mat cMat; 1040366ad2231SToby Isaac 1040466ad2231SToby Isaac PetscFunctionBegin; 1040566ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 104069566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1040766ad2231SToby Isaac if (anchorSection) { 1040844a7f3ddSMatthew G. Knepley PetscInt Nf; 10409e228b242SToby Isaac 104109566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 104119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 104129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 104139566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 104149566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 104159566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 104169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 104179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1041866ad2231SToby Isaac } 104193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1042066ad2231SToby Isaac } 10421a93c429eSMatthew G. Knepley 10422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10423d71ae5a4SJacob Faibussowitsch { 10424a93c429eSMatthew G. Knepley IS subis; 10425a93c429eSMatthew G. Knepley PetscSection section, subsection; 10426a93c429eSMatthew G. Knepley 10427a93c429eSMatthew G. Knepley PetscFunctionBegin; 104289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1042928b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1043028b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10431a93c429eSMatthew G. Knepley /* Create subdomain */ 104329566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10433a93c429eSMatthew G. Knepley /* Create submodel */ 104349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 104359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 104369566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 104379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 104389566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10439a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10440a93c429eSMatthew G. Knepley if (is) { 10441a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10442a93c429eSMatthew G. Knepley IS spIS; 10443a93c429eSMatthew G. Knepley const PetscInt *spmap; 10444a93c429eSMatthew G. Knepley PetscInt *subIndices; 10445a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10446a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10447a93c429eSMatthew G. Knepley 104489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 104499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 104509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 104519566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 104529566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 104539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10454a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10455a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10456a93c429eSMatthew G. Knepley 104579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10458a93c429eSMatthew G. Knepley if (gdof > 0) { 10459a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10460a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10461a93c429eSMatthew G. Knepley 104629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 104639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10464a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10465a93c429eSMatthew G. Knepley } 10466a93c429eSMatthew G. Knepley subSize += pSubSize; 10467a93c429eSMatthew G. Knepley if (pSubSize) { 10468a93c429eSMatthew G. Knepley if (bs < 0) { 10469a93c429eSMatthew G. Knepley bs = pSubSize; 10470a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10471a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10472a93c429eSMatthew G. Knepley bs = 1; 10473a93c429eSMatthew G. Knepley } 10474a93c429eSMatthew G. Knepley } 10475a93c429eSMatthew G. Knepley } 10476a93c429eSMatthew G. Knepley } 10477a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 104789371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 104799371c9d4SSatish Balay bsLocal[1] = bs; 104809566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 104819371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 104829371c9d4SSatish Balay bs = 1; 104839371c9d4SSatish Balay } else { 104849371c9d4SSatish Balay bs = bsMinMax[0]; 104859371c9d4SSatish Balay } 104869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10487a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10488a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10489a93c429eSMatthew G. Knepley 104909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10491a93c429eSMatthew G. Knepley if (gdof > 0) { 10492a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10493a93c429eSMatthew G. Knepley 104949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10495a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10496a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10497a93c429eSMatthew G. Knepley 10498a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10499a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 105009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 105019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10502a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10503a93c429eSMatthew G. Knepley } 105049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 105059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10506ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10507a93c429eSMatthew G. Knepley } 10508a93c429eSMatthew G. Knepley } 10509a93c429eSMatthew G. Knepley } 105109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 105119566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10512a93c429eSMatthew G. Knepley if (bs > 1) { 10513a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10514a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10515a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10516a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 105179371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 105189371c9d4SSatish Balay set = 0; 105199371c9d4SSatish Balay break; 105209371c9d4SSatish Balay } 10521a93c429eSMatthew G. Knepley } 10522a93c429eSMatthew G. Knepley } 105239566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10524a93c429eSMatthew G. Knepley } 10525a93c429eSMatthew G. Knepley /* Attach nullspace */ 10526a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10527a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10528a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10529a93c429eSMatthew G. Knepley } 10530a93c429eSMatthew G. Knepley if (f < Nf) { 10531a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 105329566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 105336823f3c5SBlaise Bourdin 105349566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 105359566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10536a93c429eSMatthew G. Knepley } 10537a93c429eSMatthew G. Knepley } 105383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10539a93c429eSMatthew G. Knepley } 10540c0f0dcc3SMatthew G. Knepley 10541c0f0dcc3SMatthew G. Knepley /*@ 10542c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10543c0f0dcc3SMatthew G. Knepley 10544a1cb98faSBarry Smith Input Parameters: 10545a1cb98faSBarry Smith + dm - The `DM` 10546a1cb98faSBarry Smith - dummy - unused argument 10547a1cb98faSBarry Smith 10548a1cb98faSBarry Smith Options Database Key: 10549a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10550c0f0dcc3SMatthew G. Knepley 10551c0f0dcc3SMatthew G. Knepley Level: developer 10552c0f0dcc3SMatthew G. Knepley 105531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10554c0f0dcc3SMatthew G. Knepley @*/ 10555d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10556d71ae5a4SJacob Faibussowitsch { 10557b665b14eSToby Isaac PetscLogHandler default_handler; 10558b665b14eSToby Isaac 105592611ad71SToby Isaac PetscFunctionBegin; 105602611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10561b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10562b665b14eSToby Isaac if (default_handler) { 10563c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10564c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10565c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10566c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10567c0f0dcc3SMatthew G. Knepley const char *name; 10568c0f0dcc3SMatthew G. Knepley 105699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 105709566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 105719566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 105729566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10573b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10574c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10575c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10576c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1057763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DM (%s) FE Residual Integration: %" PetscInt_FMT " integrals %d reps\n Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double)cellRate, (double)(flopRate / 1.e6))); 105782611ad71SToby Isaac } else { 10579b665b14eSToby Isaac SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off or the default log handler is not running. Reconfigure using --with-log and run with -log_view."); 105802611ad71SToby Isaac } 105813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10582c0f0dcc3SMatthew G. Knepley } 10583