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) { 96*c306944fSJed 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 } 104*c306944fSJed 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 1319c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1329c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1339c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1349c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1359c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1369c600e38SMatt McGurn if (field >= 0) { 1379c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1389c600e38SMatt McGurn } else { 1399c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1409c600e38SMatt McGurn } 1419c600e38SMatt McGurn 1429c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1439c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1449c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1459c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1469c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1479c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1489c600e38SMatt McGurn PetscInt dep; 1499c600e38SMatt McGurn 1509c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1519c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1529c600e38SMatt McGurn if (pStart >= 0) { 1539c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1549c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1559c600e38SMatt McGurn } 1569c600e38SMatt McGurn if (field >= 0) { 1579c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1589c600e38SMatt McGurn } else { 1599c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1609c600e38SMatt McGurn } 1619c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1629c600e38SMatt McGurn } 1639c600e38SMatt McGurn 1649c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1659c600e38SMatt McGurn *types = 0; 1669c600e38SMatt McGurn 1679c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1689c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1699c600e38SMatt McGurn } 1709c600e38SMatt McGurn 1719c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1729c600e38SMatt McGurn t = 0; 1739c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1749c600e38SMatt McGurn sStart[t] = vStart; 1759c600e38SMatt McGurn sEnd[t] = vEnd; 1769c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1779c600e38SMatt McGurn ++t; 1789c600e38SMatt McGurn } 1799c600e38SMatt McGurn 1809c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1819c600e38SMatt McGurn if (globalvcdof[c]) { 1829c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1839c600e38SMatt McGurn 1849c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1859c600e38SMatt McGurn sStart[t] = cStart; 1869c600e38SMatt McGurn sEnd[t] = cEnd; 1879c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1889c600e38SMatt McGurn ++t; 1899c600e38SMatt McGurn } 1909c600e38SMatt McGurn } 1919c600e38SMatt McGurn 1929c600e38SMatt McGurn if (!(*types)) { 1939c600e38SMatt McGurn if (field >= 0) { 1949c600e38SMatt McGurn const char *fieldname; 1959c600e38SMatt McGurn 1969c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1979c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1989c600e38SMatt McGurn } else { 1999c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 2009c600e38SMatt McGurn } 2019c600e38SMatt McGurn } 2029c600e38SMatt McGurn 2039c600e38SMatt McGurn *ssStart = sStart; 2049c600e38SMatt McGurn *ssEnd = sEnd; 2059c600e38SMatt McGurn *sft = ft; 2069c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2079c600e38SMatt McGurn } 2089c600e38SMatt McGurn 2099c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2109c600e38SMatt McGurn { 2119c600e38SMatt McGurn PetscFunctionBegin; 2129c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2139c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2149c600e38SMatt McGurn } 2159c600e38SMatt McGurn 216d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 217d71ae5a4SJacob Faibussowitsch { 218412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 219a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2207e42fee7SMatthew G. Knepley 2217e42fee7SMatthew G. Knepley PetscFunctionBegin; 222e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2259566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2277e42fee7SMatthew G. Knepley if (field >= 0) { 2289566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2299566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2307e42fee7SMatthew G. Knepley } else { 2319566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2329566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2337e42fee7SMatthew G. Knepley } 234712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 235a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2367e42fee7SMatthew G. Knepley *sStart = vStart; 2377e42fee7SMatthew G. Knepley *sEnd = vEnd; 238f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2397e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 240a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2417e42fee7SMatthew G. Knepley *sStart = cStart; 2427e42fee7SMatthew G. Knepley *sEnd = cEnd; 243f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2447e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 245e630c359SToby Isaac } else { 246e630c359SToby Isaac if (field >= 0) { 247e630c359SToby Isaac const char *fieldname; 248e630c359SToby Isaac 2499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 25063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 251e630c359SToby Isaac } else { 25263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 253e630c359SToby Isaac } 254e630c359SToby Isaac } 2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2567e42fee7SMatthew G. Knepley } 2577e42fee7SMatthew G. Knepley 2586913077dSMatthew G. Knepley /*@ 2596913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2606913077dSMatthew G. Knepley 26120f4b53cSBarry Smith Collective 2626913077dSMatthew G. Knepley 2636913077dSMatthew G. Knepley Input Parameters: 264a1cb98faSBarry Smith + dm - The `DMPLEX` object 2656913077dSMatthew G. Knepley . n - The number of vectors 2666913077dSMatthew G. Knepley . u - The array of local vectors 267a1cb98faSBarry Smith - viewer - The `PetscViewer` 2686913077dSMatthew G. Knepley 2696913077dSMatthew G. Knepley Level: advanced 2706913077dSMatthew G. Knepley 2711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2726913077dSMatthew G. Knepley @*/ 273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 274d71ae5a4SJacob Faibussowitsch { 2756913077dSMatthew G. Knepley PetscDS ds; 2766913077dSMatthew G. Knepley PetscDraw draw = NULL; 2776913077dSMatthew G. Knepley PetscDrawLG lg; 2786913077dSMatthew G. Knepley Vec coordinates; 2796913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2806913077dSMatthew G. Knepley PetscReal *vals; 2816913077dSMatthew G. Knepley PetscInt *Nc; 2826913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2836913077dSMatthew G. Knepley char **names; 2846913077dSMatthew G. Knepley 2856913077dSMatthew G. Knepley PetscFunctionBegin; 2869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2889566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2899566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2906913077dSMatthew G. Knepley 2919566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2923ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2939566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2946913077dSMatthew G. Knepley 2959566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2966913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2976913077dSMatthew G. Knepley const char *vname; 2986913077dSMatthew G. Knepley 2999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 3006913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3016913077dSMatthew G. Knepley PetscObject disc; 3026913077dSMatthew G. Knepley const char *fname; 3036913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3046913077dSMatthew G. Knepley 3059566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3066913077dSMatthew G. Knepley /* TODO Create names for components */ 3076913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 309c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 310c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 311c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3129566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3136913077dSMatthew G. Knepley } 3146913077dSMatthew G. Knepley } 3156913077dSMatthew G. Knepley } 3169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3176913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3219566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3226913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3236913077dSMatthew G. Knepley PetscScalar *x, *svals; 3246913077dSMatthew G. Knepley 3259566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3266913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3279566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3286913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3296913077dSMatthew G. Knepley } 3309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3316913077dSMatthew G. Knepley } 3329566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3339566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3349566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3359566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3366913077dSMatthew G. Knepley 3379566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3406913077dSMatthew G. Knepley } 3416913077dSMatthew G. Knepley 342d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 343d71ae5a4SJacob Faibussowitsch { 3446913077dSMatthew G. Knepley DM dm; 3456913077dSMatthew G. Knepley 3466913077dSMatthew G. Knepley PetscFunctionBegin; 3479566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3489566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3506913077dSMatthew G. Knepley } 3516913077dSMatthew G. Knepley 352d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 353d71ae5a4SJacob Faibussowitsch { 354e412dcbdSMatthew G. Knepley DM dm; 355d1df6f1dSMatthew G. Knepley PetscSection s; 356e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 357e412dcbdSMatthew G. Knepley DM cdm; 358e412dcbdSMatthew G. Knepley PetscSection coordSection; 359e412dcbdSMatthew G. Knepley Vec coordinates; 360c9c77995SMatthew G. Knepley const PetscScalar *array; 361c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 362339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3636913077dSMatthew G. Knepley PetscBool flg; 364d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 365e412dcbdSMatthew G. Knepley const char *name; 366339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 367e412dcbdSMatthew G. Knepley 368e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3699566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3709566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3729566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3749566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 380e412dcbdSMatthew G. Knepley 3819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3829566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 383e412dcbdSMatthew G. Knepley 3849566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 385c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3869566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 387e412dcbdSMatthew G. Knepley 388d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 389d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 390d1df6f1dSMatthew G. Knepley DM fdm = dm; 391d1df6f1dSMatthew G. Knepley Vec fv = v; 392d1df6f1dSMatthew G. Knepley IS fis; 393d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 394d1df6f1dSMatthew G. Knepley const char *fname; 395d1df6f1dSMatthew G. Knepley 3969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 398d1df6f1dSMatthew G. Knepley 3999566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 400ad540459SPierre Jolivet else prefix[0] = '\0'; 401d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4029566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4039566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4049566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4059566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 406d1df6f1dSMatthew G. Knepley } 407d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 408d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 409d1df6f1dSMatthew G. Knepley 4109566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 41163a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41263a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4139566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 414d1df6f1dSMatthew G. Knepley 415d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 417339e3443SMatthew G. Knepley if (!flg) { 4189566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4199566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 420d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 421339e3443SMatthew G. Knepley } 422c9c77995SMatthew G. Knepley 4239566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4249566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 425c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 427e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 42899a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 429c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 430c9c77995SMatthew G. Knepley PetscBool isDG; 431e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 432e412dcbdSMatthew G. Knepley 4339566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 434339e3443SMatthew G. Knepley if (a) { 435d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 436339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 437339e3443SMatthew G. Knepley } else { 438339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 439339e3443SMatthew G. Knepley PetscInt numVals, va; 440339e3443SMatthew G. Knepley 4419566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 44263a3b9bcSJacob 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); 443d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 444d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 445d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 446d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 447339e3443SMatthew G. Knepley break; 448d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 449d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 450d1df6f1dSMatthew 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]); 451d1df6f1dSMatthew G. Knepley break; 452d71ae5a4SJacob Faibussowitsch default: 453d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 454339e3443SMatthew G. Knepley } 4559566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 456339e3443SMatthew G. Knepley } 457c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 458e412dcbdSMatthew G. Knepley switch (numCoords) { 459e412dcbdSMatthew G. Knepley case 6: 4609edc3542SMatthew Knepley case 12: /* Localized triangle */ 4619566063dSJacob 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])); 462e412dcbdSMatthew G. Knepley break; 463e412dcbdSMatthew G. Knepley case 8: 4649edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 4659566063dSJacob 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])); 4669566063dSJacob 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])); 467e412dcbdSMatthew G. Knepley break; 468d71ae5a4SJacob Faibussowitsch default: 469d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 470e412dcbdSMatthew G. Knepley } 471c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 472e412dcbdSMatthew G. Knepley } 4739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4759566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4769566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 477d1df6f1dSMatthew G. Knepley } 478d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4799566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4819566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 482d1df6f1dSMatthew G. Knepley } 483d1df6f1dSMatthew G. Knepley } 4843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 485e412dcbdSMatthew G. Knepley } 486e412dcbdSMatthew G. Knepley 487d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 488d71ae5a4SJacob Faibussowitsch { 4896913077dSMatthew G. Knepley DM dm; 4906913077dSMatthew G. Knepley PetscDraw draw; 4916913077dSMatthew G. Knepley PetscInt dim; 4926913077dSMatthew G. Knepley PetscBool isnull; 4936913077dSMatthew G. Knepley 4946913077dSMatthew G. Knepley PetscFunctionBegin; 4959566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4969566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4973ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4986913077dSMatthew G. Knepley 4999566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5016913077dSMatthew G. Knepley switch (dim) { 502d71ae5a4SJacob Faibussowitsch case 1: 503d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 504d71ae5a4SJacob Faibussowitsch break; 505d71ae5a4SJacob Faibussowitsch case 2: 506d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 507d71ae5a4SJacob Faibussowitsch break; 508d71ae5a4SJacob Faibussowitsch default: 509d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5106913077dSMatthew G. Knepley } 5113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5126913077dSMatthew G. Knepley } 5136913077dSMatthew G. Knepley 514d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 515d71ae5a4SJacob Faibussowitsch { 516684b87d9SLisandro Dalcin DM dm; 517684b87d9SLisandro Dalcin Vec locv; 518684b87d9SLisandro Dalcin const char *name; 519684b87d9SLisandro Dalcin PetscSection section; 520684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 521e630c359SToby Isaac PetscInt numFields; 522684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 523684b87d9SLisandro Dalcin 524684b87d9SLisandro Dalcin PetscFunctionBegin; 5259566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5269566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5299566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 532e630c359SToby Isaac if (!numFields) { 5339566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 535e630c359SToby Isaac } else { 536e630c359SToby Isaac PetscInt f; 537e630c359SToby Isaac 538e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5399566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 540e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5429566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 543e630c359SToby Isaac } 5449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 545e630c359SToby Isaac } 5463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 547684b87d9SLisandro Dalcin } 548684b87d9SLisandro Dalcin 549d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 550d71ae5a4SJacob Faibussowitsch { 551552f7358SJed Brown DM dm; 5525f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 553552f7358SJed Brown 554552f7358SJed Brown PetscFunctionBegin; 5559566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 55628b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5615f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5625f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 563684b87d9SLisandro Dalcin PetscInt i, numFields; 564684b87d9SLisandro Dalcin PetscObject fe; 565ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 566684b87d9SLisandro Dalcin Vec locv = v; 567684b87d9SLisandro Dalcin const char *name; 568684b87d9SLisandro Dalcin PetscInt step; 569684b87d9SLisandro Dalcin PetscReal time; 570ef31f671SMatthew G. Knepley 5719566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 572684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5739566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5749371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5759371c9d4SSatish Balay fem = PETSC_TRUE; 5769371c9d4SSatish Balay break; 5779371c9d4SSatish Balay } 578ef31f671SMatthew G. Knepley } 579684b87d9SLisandro Dalcin if (fem) { 580798534f6SMatthew G. Knepley PetscObject isZero; 581798534f6SMatthew G. Knepley 5829566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5879566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5889566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 5899566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 590ef31f671SMatthew G. Knepley } 591552f7358SJed Brown if (isvtk) { 5929566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 593b136c2c9SMatthew G. Knepley } else if (ishdf5) { 594b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5959566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 596b136c2c9SMatthew G. Knepley #else 597b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 598b136c2c9SMatthew G. Knepley #endif 599f13a32a3SMatthew G. Knepley } else if (isdraw) { 6009566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 601684b87d9SLisandro Dalcin } else if (isglvis) { 6029566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6039566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6049566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6055f34f2dcSJed Brown } else if (iscgns) { 6065f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6075f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6085f34f2dcSJed Brown #else 6095f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6105f34f2dcSJed Brown #endif 611684b87d9SLisandro Dalcin } 612798534f6SMatthew G. Knepley if (fem) { 6139566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6149566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 615798534f6SMatthew G. Knepley } 616552f7358SJed Brown } else { 617684b87d9SLisandro Dalcin PetscBool isseq; 618684b87d9SLisandro Dalcin 6199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6209566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6219566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 622552f7358SJed Brown } 6233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 624552f7358SJed Brown } 625552f7358SJed Brown 626d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 627d71ae5a4SJacob Faibussowitsch { 628552f7358SJed Brown DM dm; 6295f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 630552f7358SJed Brown 631552f7358SJed Brown PetscFunctionBegin; 6329566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6385f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6405f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 641552f7358SJed Brown Vec locv; 642798534f6SMatthew G. Knepley PetscObject isZero; 643552f7358SJed Brown const char *name; 644552f7358SJed Brown 6459566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6509566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6529566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6539566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6549566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 655b136c2c9SMatthew G. Knepley } else if (ishdf5) { 656b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6579566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 658b136c2c9SMatthew G. Knepley #else 659b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 660b136c2c9SMatthew G. Knepley #endif 6616823f3c5SBlaise Bourdin } else if (isexodusii) { 6626823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6639566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6646823f3c5SBlaise Bourdin #else 6656823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6666823f3c5SBlaise Bourdin #endif 667552f7358SJed Brown } else { 668684b87d9SLisandro Dalcin PetscBool isseq; 669684b87d9SLisandro Dalcin 6709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6719566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6729566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 673552f7358SJed Brown } 6743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 675552f7358SJed Brown } 676552f7358SJed Brown 677d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 678d71ae5a4SJacob Faibussowitsch { 679d930f514SMatthew G. Knepley DM dm; 680d930f514SMatthew G. Knepley MPI_Comm comm; 681d930f514SMatthew G. Knepley PetscViewerFormat format; 682d930f514SMatthew G. Knepley Vec v; 683d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 684d930f514SMatthew G. Knepley 685d930f514SMatthew G. Knepley PetscFunctionBegin; 6869566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 6879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 68828b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 692d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 693a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 694a8ad634aSStefano Zampini /* this need a better fix */ 695a8ad634aSStefano Zampini if (dm->useNatural) { 696a8ad634aSStefano Zampini if (dm->sfNatural) { 697d930f514SMatthew G. Knepley const char *vecname; 698d930f514SMatthew G. Knepley PetscInt n, nroots; 699d930f514SMatthew G. Knepley 7009566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 7019566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 702d930f514SMatthew G. Knepley if (n == nroots) { 703f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7049566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 708d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 709d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 710a8ad634aSStefano Zampini } else v = originalv; 711a8ad634aSStefano Zampini } else v = originalv; 712a8ad634aSStefano Zampini 713d930f514SMatthew G. Knepley if (ishdf5) { 714d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7159566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 716d930f514SMatthew G. Knepley #else 717d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 718d930f514SMatthew G. Knepley #endif 719d930f514SMatthew G. Knepley } else if (isvtk) { 720d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 721d930f514SMatthew G. Knepley } else { 722d930f514SMatthew G. Knepley PetscBool isseq; 723d930f514SMatthew G. Knepley 7249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7259566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7269566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 727d930f514SMatthew G. Knepley } 728f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 730d930f514SMatthew G. Knepley } 731d930f514SMatthew G. Knepley 732d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 733d71ae5a4SJacob Faibussowitsch { 7342c40f234SMatthew G. Knepley DM dm; 7352c40f234SMatthew G. Knepley PetscBool ishdf5; 7362c40f234SMatthew G. Knepley 7372c40f234SMatthew G. Knepley PetscFunctionBegin; 7389566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 73928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7412c40f234SMatthew G. Knepley if (ishdf5) { 7422c40f234SMatthew G. Knepley DM dmBC; 7432c40f234SMatthew G. Knepley Vec gv; 7442c40f234SMatthew G. Knepley const char *name; 7452c40f234SMatthew G. Knepley 7469566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7509566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7529566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7539566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7541baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7562c40f234SMatthew G. Knepley } 7572c40f234SMatthew G. Knepley 758d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 759d71ae5a4SJacob Faibussowitsch { 7602c40f234SMatthew G. Knepley DM dm; 7616823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7622c40f234SMatthew G. Knepley 7632c40f234SMatthew G. Knepley PetscFunctionBegin; 7649566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76528b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7682c40f234SMatthew G. Knepley if (ishdf5) { 769878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7709566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 771b136c2c9SMatthew G. Knepley #else 772b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 773878b459fSMatthew G. Knepley #endif 7746823f3c5SBlaise Bourdin } else if (isexodusii) { 7756823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7769566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7776823f3c5SBlaise Bourdin #else 7786823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7796823f3c5SBlaise Bourdin #endif 7801baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 782552f7358SJed Brown } 783552f7358SJed Brown 784d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 785d71ae5a4SJacob Faibussowitsch { 786d930f514SMatthew G. Knepley DM dm; 787d930f514SMatthew G. Knepley PetscViewerFormat format; 788d930f514SMatthew G. Knepley PetscBool ishdf5; 789d930f514SMatthew G. Knepley 790d930f514SMatthew G. Knepley PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 79228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7939566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 795d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 796a8ad634aSStefano Zampini if (dm->useNatural) { 797d930f514SMatthew G. Knepley if (dm->sfNatural) { 798d930f514SMatthew G. Knepley if (ishdf5) { 799d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 800d930f514SMatthew G. Knepley Vec v; 801d930f514SMatthew G. Knepley const char *vecname; 802d930f514SMatthew G. Knepley 803f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8069566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8079566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8089566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 809f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 810d930f514SMatthew G. Knepley #else 811d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 812d930f514SMatthew G. Knepley #endif 813d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 814d930f514SMatthew G. Knepley } 8151baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 816d930f514SMatthew G. Knepley } 8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 818d930f514SMatthew G. Knepley } 819d930f514SMatthew G. Knepley 820d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 821d71ae5a4SJacob Faibussowitsch { 822731e8ddeSMatthew G. Knepley PetscSection coordSection; 823731e8ddeSMatthew G. Knepley Vec coordinates; 824ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 825731e8ddeSMatthew G. Knepley const char *name[4]; 826731e8ddeSMatthew G. Knepley const PetscScalar *a; 827731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 828731e8ddeSMatthew G. Knepley 829731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 838731e8ddeSMatthew G. Knepley name[0] = "vertex"; 839731e8ddeSMatthew G. Knepley name[1] = "edge"; 840731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 841731e8ddeSMatthew G. Knepley name[dim] = "cell"; 842731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 843731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 844ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 845731e8ddeSMatthew G. Knepley 8469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 84763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 850731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 851731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 852731e8ddeSMatthew G. Knepley 853731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 855731e8ddeSMatthew G. Knepley if (!dof) continue; 8569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 85863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 859731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 861731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8629566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 864731e8ddeSMatthew G. Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 866731e8ddeSMatthew G. Knepley } 8679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 868731e8ddeSMatthew G. Knepley } 8699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 871731e8ddeSMatthew G. Knepley } 8729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 874731e8ddeSMatthew G. Knepley } 875731e8ddeSMatthew G. Knepley 8769371c9d4SSatish Balay typedef enum { 8779371c9d4SSatish Balay CS_CARTESIAN, 8789371c9d4SSatish Balay CS_POLAR, 8799371c9d4SSatish Balay CS_CYLINDRICAL, 8809371c9d4SSatish Balay CS_SPHERICAL 8819371c9d4SSatish Balay } CoordSystem; 88219ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 88319ad8254SMatthew G. Knepley 884d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 885d71ae5a4SJacob Faibussowitsch { 88619ad8254SMatthew G. Knepley PetscInt i; 88719ad8254SMatthew G. Knepley 88819ad8254SMatthew G. Knepley PetscFunctionBegin; 88919ad8254SMatthew G. Knepley if (dim > 3) { 8909566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 89119ad8254SMatthew G. Knepley } else { 892bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 89319ad8254SMatthew G. Knepley 89419ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 89519ad8254SMatthew G. Knepley switch (cs) { 8969371c9d4SSatish Balay case CS_CARTESIAN: 8979371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8989371c9d4SSatish Balay break; 89919ad8254SMatthew G. Knepley case CS_POLAR: 90063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 90119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90319ad8254SMatthew G. Knepley break; 90419ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 90563a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 90619ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90719ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90819ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 90919ad8254SMatthew G. Knepley break; 91019ad8254SMatthew G. Knepley case CS_SPHERICAL: 91163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 91219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 91319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 91419ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 91519ad8254SMatthew G. Knepley break; 91619ad8254SMatthew G. Knepley } 9179566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 91819ad8254SMatthew G. Knepley } 9193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92019ad8254SMatthew G. Knepley } 92119ad8254SMatthew G. Knepley 922d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 923d71ae5a4SJacob Faibussowitsch { 924552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9256858538eSMatthew G. Knepley DM cdm, cdmCell; 9266858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9276858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 928552f7358SJed Brown PetscViewerFormat format; 929552f7358SJed Brown 930552f7358SJed Brown PetscFunctionBegin; 9319566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 932552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 933552f7358SJed Brown const char *name; 934f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9359318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 936552f7358SJed Brown PetscMPIInt rank, size; 937552f7358SJed Brown 9389f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9399f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9409f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9419f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9429f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9439f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9489566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9509566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 95263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 95363a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 95463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 95663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 957552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 958552f7358SJed Brown PetscInt dof, off, s; 959552f7358SJed Brown 9609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 96248a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 963552f7358SJed Brown } 9649566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 96563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 96663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 967552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 968552f7358SJed Brown PetscInt dof, off, c; 969552f7358SJed Brown 9709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 97248a46eb9SPierre 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])); 973552f7358SJed Brown } 9749566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9763d2e540fSStefano Zampini if (coordSection && coordinates) { 97719ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9786858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 9796858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 98019ad8254SMatthew G. Knepley PetscMPIInt rank; 98119ad8254SMatthew G. Knepley const char *name; 98219ad8254SMatthew G. Knepley 9839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 9849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 9859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 98663a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 9879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 9886858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 9896858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 9906858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 9916858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 9929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 99363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 99463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9959566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 99619ad8254SMatthew G. Knepley 9979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9986858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 10009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 100119ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 100219ad8254SMatthew G. Knepley PetscInt dof, off; 100319ad8254SMatthew G. Knepley 10046858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10076858538eSMatthew G. Knepley if (dof) { 100863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10099566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 101119ad8254SMatthew G. Knepley } 10126858538eSMatthew G. Knepley } 10136858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10146858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10156858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10166858538eSMatthew G. Knepley if (dof) { 10176858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10186858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10196858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10206858538eSMatthew G. Knepley } 10216858538eSMatthew G. Knepley } 10226858538eSMatthew G. Knepley } 10239566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10266858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10273d2e540fSStefano Zampini } 10289566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10299566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10309318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10319318fe57SMatthew G. Knepley DMLabel label; 10329318fe57SMatthew G. Knepley PetscBool isdepth; 10339318fe57SMatthew G. Knepley const char *name; 10349318fe57SMatthew G. Knepley 10359566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10379318fe57SMatthew G. Knepley if (isdepth) continue; 10389566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10399566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10409318fe57SMatthew G. Knepley } 1041552f7358SJed Brown if (size > 1) { 1042552f7358SJed Brown PetscSF sf; 1043552f7358SJed Brown 10449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10459566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1046552f7358SJed Brown } 10474e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 10489566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1049552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10500588280cSMatthew G. Knepley const char *name, *color; 10510588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10520588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1053fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1054552f7358SJed Brown PetscReal scale = 2.0; 105578081901SStefano Zampini PetscReal tikzscale = 1.0; 1056b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10570588280cSMatthew G. Knepley double tcoords[3]; 1058552f7358SJed Brown PetscScalar *coords; 1059b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 1060552f7358SJed Brown PetscMPIInt rank, size; 10610588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1062b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1063fe1cc32dSStefano Zampini PetscBT wp = NULL; 1064fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1065552f7358SJed Brown 10669f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10679f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10689f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10699f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10709f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10719f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10729566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10749566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10750588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10760588280cSMatthew G. Knepley numColors = 10; 10770588280cSMatthew G. Knepley numLColors = 10; 10789566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 10799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 10809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 10819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1082b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1083b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1084b7f6ffafSMatthew G. Knepley n = 4; 10859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 10861dca8a05SBarry 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); 10879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10881dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 10899566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10900588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10919566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10920588280cSMatthew G. Knepley if (!useColors) { 10930588280cSMatthew G. Knepley numColors = 3; 10949566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10950588280cSMatthew G. Knepley } 10969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10970588280cSMatthew G. Knepley if (!useColors) { 10980588280cSMatthew G. Knepley numLColors = 4; 10999566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11000588280cSMatthew G. Knepley } 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1102b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11041dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1105202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1107fe1cc32dSStefano Zampini 1108fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1113fe1cc32dSStefano Zampini if (lflg) { 1114fe1cc32dSStefano Zampini DMLabel lbl; 1115fe1cc32dSStefano Zampini 11169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1117fe1cc32dSStefano Zampini if (lbl) { 1118fe1cc32dSStefano Zampini PetscInt val, defval; 1119fe1cc32dSStefano Zampini 11209566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11219566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1122fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1123fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1124fe1cc32dSStefano Zampini PetscInt closureSize; 1125fe1cc32dSStefano Zampini 11269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1127fe1cc32dSStefano Zampini if (val == defval) continue; 1128fe1cc32dSStefano Zampini 11299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 113048a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11319566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1132fe1cc32dSStefano Zampini } 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini } 1135fe1cc32dSStefano Zampini 11369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11400588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1141552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1142552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1143552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11445f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11450588280cSMatthew G. Knepley if (size > 1) { 11469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1147770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114863a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 114963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1150770b213bSMatthew G Knepley } 11519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11520588280cSMatthew G. Knepley } 1153b7f6ffafSMatthew G. Knepley if (drawHasse) { 1154b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1155b7f6ffafSMatthew G. Knepley 115663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 116063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1168b7f6ffafSMatthew G. Knepley } 11699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1170fe1cc32dSStefano Zampini 1171552f7358SJed Brown /* Plot vertices */ 11729566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1174552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1175552f7358SJed Brown PetscInt off, dof, d; 11760588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1177552f7358SJed Brown 1178fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118263a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11830588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11840588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1185c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11860588280cSMatthew G. Knepley } 11870588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11889371c9d4SSatish Balay if (dim == 3) { 11899371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11909371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11919371c9d4SSatish Balay tcoords[2] = -tmp; 11929371c9d4SSatish Balay } 1193552f7358SJed Brown for (d = 0; d < dof; ++d) { 11949566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1196552f7358SJed Brown } 1197b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1198b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 11990588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12000588280cSMatthew G. Knepley PetscInt val; 12019566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12029371c9d4SSatish Balay if (val >= 0) { 12039371c9d4SSatish Balay color = lcolors[l % numLColors]; 12049371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12059371c9d4SSatish Balay break; 12069371c9d4SSatish Balay } 12070588280cSMatthew G. Knepley } 1208b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 120963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1210b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12121baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1213552f7358SJed Brown } 12149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12159566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1216b7f6ffafSMatthew G. Knepley /* Plot edges */ 1217b7f6ffafSMatthew G. Knepley if (plotEdges) { 12189566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1220b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1221b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1222b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1223b7f6ffafSMatthew G. Knepley 1224b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122663a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1232b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1233b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1234b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1235b7f6ffafSMatthew G. Knepley } 1236b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12379371c9d4SSatish Balay if (dim == 3) { 12389371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12399371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12409371c9d4SSatish Balay tcoords[2] = -tmp; 12419371c9d4SSatish Balay } 1242b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12439566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1245b7f6ffafSMatthew G. Knepley } 1246b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1247b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1248b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1249b7f6ffafSMatthew G. Knepley PetscInt val; 12509566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12519371c9d4SSatish Balay if (val >= 0) { 12529371c9d4SSatish Balay color = lcolors[l % numLColors]; 12539371c9d4SSatish Balay break; 12549371c9d4SSatish Balay } 1255b7f6ffafSMatthew G. Knepley } 125663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1257b7f6ffafSMatthew G. Knepley } 12589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1261b7f6ffafSMatthew G. Knepley } 1262846a3e8bSMatthew G. Knepley /* Plot cells */ 1263b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1264846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1265846a3e8bSMatthew G. Knepley const PetscInt *cone; 1266846a3e8bSMatthew G. Knepley 1267fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1268846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1269846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1270846a3e8bSMatthew G. Knepley PetscInt val; 12719566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12729371c9d4SSatish Balay if (val >= 0) { 12739371c9d4SSatish Balay color = lcolors[l % numLColors]; 12749371c9d4SSatish Balay break; 12759371c9d4SSatish Balay } 1276846a3e8bSMatthew G. Knepley } 12779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1279846a3e8bSMatthew G. Knepley } 1280846a3e8bSMatthew G. Knepley } else { 1281b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1282846a3e8bSMatthew G. Knepley 1283b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1284b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1285fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1287*c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1288b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1289b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1290b7f6ffafSMatthew G. Knepley 12919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1293b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1294b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1295b7f6ffafSMatthew G. Knepley 12969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1298b7f6ffafSMatthew G. Knepley } 1299b7f6ffafSMatthew G. Knepley } else { 1300b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1301b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1302b7f6ffafSMatthew G. Knepley 13039566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1304846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1305846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1306846a3e8bSMatthew G. Knepley 1307b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1308846a3e8bSMatthew G. Knepley } 13099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1310b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1311b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1312b7f6ffafSMatthew G. Knepley 1313b7f6ffafSMatthew G. Knepley if (v > 0) { 1314b7f6ffafSMatthew G. Knepley if (plotEdges) { 1315b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1316b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1317b7f6ffafSMatthew G. Knepley 13189371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13199371c9d4SSatish Balay endpoints[1] = vertex; 13209566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132163a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13241baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1325b7f6ffafSMatthew G. Knepley } 132663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1327b7f6ffafSMatthew G. Knepley } 13289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1330846a3e8bSMatthew G. Knepley } 1331846a3e8bSMatthew G. Knepley } 1332b7f6ffafSMatthew G. Knepley } 1333846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1334846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1335846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1336c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1337c713ec31SMatthew G. Knepley const PetscScalar *array; 1338c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1339c713ec31SMatthew G. Knepley PetscBool isDG; 1340846a3e8bSMatthew G. Knepley 1341fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1342c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1343c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1344c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1346c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1347c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1348c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1349846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1350846a3e8bSMatthew G. Knepley } 1351846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13529371c9d4SSatish Balay if (cdim == 3) { 13539371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13549371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13559371c9d4SSatish Balay tcoords[2] = -tmp; 13569371c9d4SSatish Balay } 1357ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1358846a3e8bSMatthew G. Knepley } 1359ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1360c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1361c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13629566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1364846a3e8bSMatthew G. Knepley } 1365b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1366b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1367846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1368846a3e8bSMatthew G. Knepley PetscInt val; 13699566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13709371c9d4SSatish Balay if (val >= 0) { 13719371c9d4SSatish Balay color = lcolors[l % numLColors]; 13729371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13739371c9d4SSatish Balay break; 13749371c9d4SSatish Balay } 1375846a3e8bSMatthew G. Knepley } 1376b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1378b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 137963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13801baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1381846a3e8bSMatthew G. Knepley } 1382b7f6ffafSMatthew G. Knepley if (drawHasse) { 1383b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1389552f7358SJed Brown 1390b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1396b7f6ffafSMatthew G. Knepley 1397b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1403b7f6ffafSMatthew G. Knepley 1404b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1405b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1406b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1407b7f6ffafSMatthew G. Knepley 14089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 141048a46eb9SPierre Jolivet for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 14110588280cSMatthew G. Knepley } 14120588280cSMatthew G. Knepley } 14139566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14179566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14189566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14199566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14209566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14219566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14220f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14230f7d6e4aSStefano Zampini Vec cown, acown; 14240f7d6e4aSStefano Zampini VecScatter sct; 14250f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14260f7d6e4aSStefano Zampini IS gid, acis; 14270f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14280f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14290f7d6e4aSStefano Zampini PetscScalar *array, nid; 14300f7d6e4aSStefano Zampini const PetscInt *idxs; 14310f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14320f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14330f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14340f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14350f7d6e4aSStefano Zampini 14369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1438b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14400f7d6e4aSStefano Zampini #endif 14410f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14440f7d6e4aSStefano Zampini d1 = 0; 14459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14460f7d6e4aSStefano Zampini nid = d2; 14479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14500f7d6e4aSStefano Zampini } else nid = 0.0; 14510f7d6e4aSStefano Zampini 14520f7d6e4aSStefano Zampini /* Get connectivity */ 14539566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14549566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14550f7d6e4aSStefano Zampini 14560f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14610f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14620f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14630f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14640f7d6e4aSStefano Zampini } 14659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146663a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14690f7d6e4aSStefano Zampini 14700f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14729566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14739566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14749566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14750f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14769566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14779566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14799566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14819566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14830f7d6e4aSStefano Zampini 14840f7d6e4aSStefano Zampini /* compute edgeCut */ 14850f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14909566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14910f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14920f7d6e4aSStefano Zampini PetscInt totl; 14930f7d6e4aSStefano Zampini 14940f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14959566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14960f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14970f7d6e4aSStefano Zampini if (work[i] < 0) { 14980f7d6e4aSStefano Zampini ect += 1; 14990f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 15000f7d6e4aSStefano Zampini } 15010f7d6e4aSStefano Zampini } 15020f7d6e4aSStefano Zampini } 15039566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15050f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15060f7d6e4aSStefano Zampini lm[1] = -numVertices; 15071c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0])); 15090f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15100f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15110f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1514b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 151563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)(gm[1])) / ((double)gm[0]) : 1.)); 15160f7d6e4aSStefano Zampini #else 151763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15180f7d6e4aSStefano Zampini #endif 15199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15219566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1523552f7358SJed Brown } else { 1524412e9a14SMatthew G. Knepley const char *name; 1525d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1526412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1527d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1528ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15299318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1530412e9a14SMatthew G. Knepley MPI_Comm comm; 1531412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1532552f7358SJed Brown 15339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15369566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15379566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15389566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 153963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 154063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154163a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15431c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15442827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1545d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15469566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15479566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1548412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1549412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1550412e9a14SMatthew G. Knepley 15519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15529566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1553412e9a14SMatthew G. Knepley ict = ct0; 15549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1555412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1556412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1557412e9a14SMatthew G. Knepley DMPolytopeType ct; 1558412e9a14SMatthew G. Knepley 15599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1560412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1561412e9a14SMatthew G. Knepley else ++Nc[1]; 1562412e9a14SMatthew G. Knepley } 1563ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15669566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1568834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1569dd400576SPatrick Sanan if (rank == 0) { 157063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157163a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157263a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1573834065abSMatthew G. Knepley } 1574cbb7f117SMark Adams } 1575ca7bf7eeSMatthew G. Knepley } else { 1576ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1577ca7bf7eeSMatthew G. Knepley 15789371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15799371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15809566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15819371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15829371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15839566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1584ca7bf7eeSMatthew G. Knepley if (d == depth) { 15859371c9d4SSatish Balay locMinMax[0] = gcNum; 15869371c9d4SSatish Balay locMinMax[1] = gcNum; 15879566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1588ca7bf7eeSMatthew G. Knepley } 158963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15919566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15929566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1593ca7bf7eeSMatthew G. Knepley } 15949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1595552f7358SJed Brown } 15969566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15979318fe57SMatthew G. Knepley { 15989318fe57SMatthew G. Knepley const PetscReal *maxCell; 15999318fe57SMatthew G. Knepley const PetscReal *L; 16006858538eSMatthew G. Knepley PetscBool localized; 16019318fe57SMatthew G. Knepley 16024fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16046858538eSMatthew G. Knepley if (L || localized) { 16056858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16076858538eSMatthew G. Knepley if (L) { 16086858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16099318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16106858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16116858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16129318fe57SMatthew G. Knepley } 16136858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16146858538eSMatthew G. Knepley } 16156858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16179318fe57SMatthew G. Knepley } 16189318fe57SMatthew G. Knepley } 16199566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16209566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1621a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1622a57dd577SMatthew G Knepley DMLabel label; 1623a57dd577SMatthew G Knepley const char *name; 1624a57dd577SMatthew G Knepley IS valueIS; 1625a57dd577SMatthew G Knepley const PetscInt *values; 1626a57dd577SMatthew G Knepley PetscInt numValues, v; 1627a57dd577SMatthew G Knepley 16289566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16309566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16329566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1635a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1636a57dd577SMatthew G Knepley PetscInt size; 1637a57dd577SMatthew G Knepley 16389566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16399566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 164063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1641a57dd577SMatthew G Knepley } 16429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1646a57dd577SMatthew G Knepley } 1647c1cad2e7SMatthew G. Knepley { 1648c1cad2e7SMatthew G. Knepley char **labelNames; 1649c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1650c1cad2e7SMatthew G. Knepley PetscBool flg; 1651c1cad2e7SMatthew G. Knepley 16529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16539566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1654c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1655c1cad2e7SMatthew G. Knepley DMLabel label; 1656c1cad2e7SMatthew G. Knepley 16579566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1658c1cad2e7SMatthew G. Knepley if (flg) { 16599566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16609566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1661c1cad2e7SMatthew G. Knepley } 16629566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1663c1cad2e7SMatthew G. Knepley } 16649566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1665c1cad2e7SMatthew G. Knepley } 166634aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166734aa8a36SMatthew G. Knepley if (dm->Nf) { 166834aa8a36SMatthew G. Knepley PetscInt f; 166934aa8a36SMatthew G. Knepley 167034aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167134aa8a36SMatthew G. Knepley const char *name; 167234aa8a36SMatthew G. Knepley 16739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16749566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16769566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167734aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16789566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16799566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 168034aa8a36SMatthew G. Knepley } else { 16819566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16829566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168334aa8a36SMatthew G. Knepley } 16849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168534aa8a36SMatthew G. Knepley } 168634aa8a36SMatthew G. Knepley } 16879566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16888e7ff633SMatthew G. Knepley if (cdm) { 16899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16909f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16919566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16938e7ff633SMatthew G. Knepley } 1694552f7358SJed Brown } 16953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1696552f7358SJed Brown } 1697552f7358SJed Brown 1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1699d71ae5a4SJacob Faibussowitsch { 1700e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1701e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1702a12d352dSMatthew G. Knepley PetscInt cdim; 1703e5c487bfSMatthew G. Knepley 1704e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1708e5c487bfSMatthew G. Knepley switch (ct) { 1709a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1710a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1711a12d352dSMatthew G. Knepley switch (cdim) { 17129371c9d4SSatish Balay case 1: { 1713a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1714a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1715a12d352dSMatthew G. Knepley 17169566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17189566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17199371c9d4SSatish Balay } break; 17209371c9d4SSatish Balay case 2: { 1721a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1722a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1723a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1724a12d352dSMatthew G. Knepley 17259566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK)); 17279566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK)); 17289371c9d4SSatish Balay } break; 1729d71ae5a4SJacob Faibussowitsch default: 1730d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1731a12d352dSMatthew G. Knepley } 1732a12d352dSMatthew G. Knepley break; 1733e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17349371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17359566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17379566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1738e5c487bfSMatthew G. Knepley break; 1739e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17409371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17419371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17459566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1746e5c487bfSMatthew G. Knepley break; 17479f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17489f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17499f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17509f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17549f4ada15SMatthew G. Knepley break; 1755d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1756d71ae5a4SJacob Faibussowitsch break; 1757d71ae5a4SJacob Faibussowitsch default: 1758d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1759e5c487bfSMatthew G. Knepley } 17603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1761e5c487bfSMatthew G. Knepley } 1762e5c487bfSMatthew G. Knepley 1763d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1764d71ae5a4SJacob Faibussowitsch { 1765e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1766e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1767e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1768e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1769e5c487bfSMatthew G. Knepley 1770e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1773e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1774e5c487bfSMatthew G. Knepley switch (ct) { 17759371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 1776e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1777e5c487bfSMatthew G. Knepley 17789371c9d4SSatish Balay for (v = 0; v < 3; ++v) { 17799371c9d4SSatish Balay centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.; 17809371c9d4SSatish Balay centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.; 17819371c9d4SSatish Balay } 1782e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1783e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1784e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1785e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1786e5c487bfSMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv; 1787e5c487bfSMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv; 1788e5c487bfSMatthew G. Knepley } 17899566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1790e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 17919566063dSJacob 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)); 17929566063dSJacob 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)); 1793e5c487bfSMatthew G. Knepley } 1794e5c487bfSMatthew G. Knepley } 17959371c9d4SSatish Balay } break; 1796d71ae5a4SJacob Faibussowitsch default: 1797d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1798e5c487bfSMatthew G. Knepley } 17993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1800e5c487bfSMatthew G. Knepley } 1801e5c487bfSMatthew G. Knepley 1802d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1803d71ae5a4SJacob Faibussowitsch { 1804e412dcbdSMatthew G. Knepley PetscDraw draw; 1805e412dcbdSMatthew G. Knepley DM cdm; 1806e412dcbdSMatthew G. Knepley PetscSection coordSection; 1807e412dcbdSMatthew G. Knepley Vec coordinates; 1808c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1809e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1810e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1811c9c77995SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4; 1812e412dcbdSMatthew G. Knepley 1813e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 181563a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 18169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18179566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18219566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1823e412dcbdSMatthew G. Knepley 18249566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18259566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18263ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18279566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1828e412dcbdSMatthew G. Knepley 1829c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18309566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18319566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1832e412dcbdSMatthew G. Knepley 1833cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1834cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1835c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1836ba2698f1SMatthew G. Knepley PetscInt numCoords; 1837c9c77995SMatthew G. Knepley PetscBool isDG; 1838cf3064d3SMatthew G. Knepley 1839c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18401baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18411baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1842c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1843cf3064d3SMatthew G. Knepley } 18449566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18459566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18469566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18479566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1849e412dcbdSMatthew G. Knepley } 1850e412dcbdSMatthew G. Knepley 1851e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1852e44f6aebSMatthew G. Knepley { 1853e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1854e44f6aebSMatthew G. Knepley PetscFE fe; 1855e44f6aebSMatthew G. Knepley PetscSpace sp; 1856e44f6aebSMatthew G. Knepley PetscClassId id; 1857e44f6aebSMatthew G. Knepley PetscInt degree; 1858e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1859e44f6aebSMatthew G. Knepley 1860e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1861e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1862e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1863e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1864e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1865e44f6aebSMatthew G. Knepley *hdm = dm; 1866e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1867e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1868e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1869e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1870e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1871e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1872e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1873e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1874e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1875e44f6aebSMatthew G. Knepley Mat In; 1876e44f6aebSMatthew G. Knepley Vec cl, rcl; 1877e44f6aebSMatthew G. Knepley 1878e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1879e44f6aebSMatthew G. Knepley if (rd > 1) PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1880e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1881e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1882e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1883e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1884e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1885e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1886e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1887e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1888e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1889e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1890e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1891e44f6aebSMatthew G. Knepley odm = rdm; 1892e44f6aebSMatthew G. Knepley } 1893e44f6aebSMatthew G. Knepley *hdm = rdm; 1894e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1895e44f6aebSMatthew G. Knepley } 1896e44f6aebSMatthew G. Knepley 18971e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 18981e50132fSMatthew G. Knepley #include <exodusII.h> 18996823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19001e50132fSMatthew G. Knepley #endif 19011e50132fSMatthew G. Knepley 1902d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1903d71ae5a4SJacob Faibussowitsch { 19045f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1905002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1906552f7358SJed Brown 1907552f7358SJed Brown PetscFunctionBegin; 1908552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1909552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19165f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1917552f7358SJed Brown if (iascii) { 19188135c375SStefano Zampini PetscViewerFormat format; 19199566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19201baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19211baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1922c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1923c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19249566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1925c6ccd67eSMatthew G. Knepley #else 1926c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1927552f7358SJed Brown #endif 1928e412dcbdSMatthew G. Knepley } else if (isvtk) { 19299566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1930e412dcbdSMatthew G. Knepley } else if (isdraw) { 1931e44f6aebSMatthew G. Knepley DM hdm; 1932e44f6aebSMatthew G. Knepley 1933e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1934e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1935e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19368135c375SStefano Zampini } else if (isglvis) { 19379566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19381e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19391e50132fSMatthew G. Knepley } else if (isexodus) { 19406823f3c5SBlaise Bourdin /* 19416823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19426823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1943da81f932SPierre Jolivet with ID 1, containing all cells. 19446823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19456823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19466823f3c5SBlaise Bourdin */ 19476823f3c5SBlaise Bourdin PetscInt numCS; 19489566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19496823f3c5SBlaise Bourdin if (!numCS) { 19501e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19539566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19546823f3c5SBlaise Bourdin } 19559566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19561e50132fSMatthew G. Knepley #endif 19575f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19585f34f2dcSJed Brown } else if (iscgns) { 19595f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19605f34f2dcSJed Brown #endif 19611baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1962cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19639566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1964cb3ba0daSMatthew G. Knepley if (flg) { 1965cb3ba0daSMatthew G. Knepley Vec ranks; 19669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19679566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19689566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1969cb3ba0daSMatthew G. Knepley } 1970002a2709SMatthew G. Knepley /* Optionally view a label */ 19719566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1972002a2709SMatthew G. Knepley if (flg) { 1973002a2709SMatthew G. Knepley DMLabel label; 1974002a2709SMatthew G. Knepley Vec val; 1975002a2709SMatthew G. Knepley 19769566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 197728b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19799566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1981002a2709SMatthew G. Knepley } 19823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1983552f7358SJed Brown } 1984552f7358SJed Brown 19857f96f51bSksagiyam /*@ 1986a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 19877f96f51bSksagiyam 198820f4b53cSBarry Smith Collective 19897f96f51bSksagiyam 19907f96f51bSksagiyam Input Parameters: 1991a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 1992a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 19937f96f51bSksagiyam 19947f96f51bSksagiyam Level: advanced 19957f96f51bSksagiyam 19961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 19977f96f51bSksagiyam @*/ 1998d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 1999d71ae5a4SJacob Faibussowitsch { 20007f96f51bSksagiyam PetscBool ishdf5; 20017f96f51bSksagiyam 20027f96f51bSksagiyam PetscFunctionBegin; 20037f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20047f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20077f96f51bSksagiyam if (ishdf5) { 20087f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20097f96f51bSksagiyam PetscViewerFormat format; 20109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20117f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20127f96f51bSksagiyam IS globalPointNumbering; 20137f96f51bSksagiyam 20149566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20159566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 201798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20187f96f51bSksagiyam #else 20197f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20207f96f51bSksagiyam #endif 20217f96f51bSksagiyam } 20229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20247f96f51bSksagiyam } 20257f96f51bSksagiyam 202677b8e257Sksagiyam /*@ 2027a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 202877b8e257Sksagiyam 202920f4b53cSBarry Smith Collective 203077b8e257Sksagiyam 203177b8e257Sksagiyam Input Parameters: 2032a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2033a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 203477b8e257Sksagiyam 203577b8e257Sksagiyam Level: advanced 203677b8e257Sksagiyam 20371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 203877b8e257Sksagiyam @*/ 2039d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2040d71ae5a4SJacob Faibussowitsch { 204177b8e257Sksagiyam PetscBool ishdf5; 204277b8e257Sksagiyam 204377b8e257Sksagiyam PetscFunctionBegin; 204477b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204577b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 204877b8e257Sksagiyam if (ishdf5) { 204977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 205077b8e257Sksagiyam PetscViewerFormat format; 20519566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 205277b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20539566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2054fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 205577b8e257Sksagiyam #else 205677b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 205777b8e257Sksagiyam #endif 205877b8e257Sksagiyam } 20599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 206177b8e257Sksagiyam } 206277b8e257Sksagiyam 2063bd6565f1Sksagiyam /*@ 2064a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2065bd6565f1Sksagiyam 206620f4b53cSBarry Smith Collective 2067bd6565f1Sksagiyam 2068bd6565f1Sksagiyam Input Parameters: 2069a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2070a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2071bd6565f1Sksagiyam 2072bd6565f1Sksagiyam Level: advanced 2073bd6565f1Sksagiyam 20741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2075bd6565f1Sksagiyam @*/ 2076d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2077d71ae5a4SJacob Faibussowitsch { 2078bd6565f1Sksagiyam PetscBool ishdf5; 2079bd6565f1Sksagiyam 2080bd6565f1Sksagiyam PetscFunctionBegin; 2081bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2082bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2085bd6565f1Sksagiyam if (ishdf5) { 2086bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2087bd6565f1Sksagiyam IS globalPointNumbering; 2088bd6565f1Sksagiyam PetscViewerFormat format; 2089bd6565f1Sksagiyam 20909566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2091bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20929566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20939566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 209598921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2096bd6565f1Sksagiyam #else 2097bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2098bd6565f1Sksagiyam #endif 2099bd6565f1Sksagiyam } 21009566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2102bd6565f1Sksagiyam } 2103bd6565f1Sksagiyam 2104021affd3Sksagiyam /*@ 2105a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2106021affd3Sksagiyam 210720f4b53cSBarry Smith Collective 2108021affd3Sksagiyam 2109021affd3Sksagiyam Input Parameters: 2110a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2111a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 2112a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved 2113021affd3Sksagiyam 2114021affd3Sksagiyam Level: advanced 2115021affd3Sksagiyam 2116021affd3Sksagiyam Notes: 2117420bcc1bSBarry 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. 2118021affd3Sksagiyam 2119420bcc1bSBarry Smith 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 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. 2120021affd3Sksagiyam 21211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2122021affd3Sksagiyam @*/ 2123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2124d71ae5a4SJacob Faibussowitsch { 2125021affd3Sksagiyam PetscBool ishdf5; 2126021affd3Sksagiyam 2127021affd3Sksagiyam PetscFunctionBegin; 2128021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2129021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2130021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2133021affd3Sksagiyam if (ishdf5) { 2134021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21359566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2136021affd3Sksagiyam #else 2137021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2138021affd3Sksagiyam #endif 2139021affd3Sksagiyam } 21409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2142021affd3Sksagiyam } 2143021affd3Sksagiyam 21443e97647fSksagiyam /*@ 21453e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21463e97647fSksagiyam 214720f4b53cSBarry Smith Collective 21483e97647fSksagiyam 21493e97647fSksagiyam Input Parameters: 2150a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2151a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2152a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 21533e97647fSksagiyam - vec - The global vector to be saved 21543e97647fSksagiyam 21553e97647fSksagiyam Level: advanced 21563e97647fSksagiyam 21573e97647fSksagiyam Notes: 2158420bcc1bSBarry Smith 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 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. 21593e97647fSksagiyam 216060225df5SJacob Faibussowitsch Calling sequence: 2161a1cb98faSBarry Smith .vb 2162a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2163a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2164a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2165a1cb98faSBarry Smith DMClone(dm, §iondm); 2166a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2167a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2168a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2169a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2170a1cb98faSBarry Smith PetscSectionSetUp(section); 2171a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2172a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2173a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2174a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2175a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2176a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2177a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2178a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2179a1cb98faSBarry Smith DMDestroy(§iondm); 2180a1cb98faSBarry Smith DMDestroy(&dm); 2181a1cb98faSBarry Smith .ve 21823e97647fSksagiyam 21831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 21843e97647fSksagiyam @*/ 2185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2186d71ae5a4SJacob Faibussowitsch { 21873e97647fSksagiyam PetscBool ishdf5; 21883e97647fSksagiyam 21893e97647fSksagiyam PetscFunctionBegin; 21903e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21913e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21923e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21933e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 21943e97647fSksagiyam /* Check consistency */ 21953e97647fSksagiyam { 21963e97647fSksagiyam PetscSection section; 21973e97647fSksagiyam PetscBool includesConstraints; 21983e97647fSksagiyam PetscInt m, m1; 21993e97647fSksagiyam 22009566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22019566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22039566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22049566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 220563a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22063e97647fSksagiyam } 22079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22093e97647fSksagiyam if (ishdf5) { 22103e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22119566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22123e97647fSksagiyam #else 22133e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22143e97647fSksagiyam #endif 22153e97647fSksagiyam } 22169566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22183e97647fSksagiyam } 22193e97647fSksagiyam 22203e97647fSksagiyam /*@ 22213e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22223e97647fSksagiyam 222320f4b53cSBarry Smith Collective 22243e97647fSksagiyam 22253e97647fSksagiyam Input Parameters: 2226a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2227a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 222820f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm` 22293e97647fSksagiyam - vec - The local vector to be saved 22303e97647fSksagiyam 22313e97647fSksagiyam Level: advanced 22323e97647fSksagiyam 2233a1cb98faSBarry Smith Note: 223420f4b53cSBarry Smith 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 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. 22353e97647fSksagiyam 223660225df5SJacob Faibussowitsch Calling sequence: 2237a1cb98faSBarry Smith .vb 2238a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2239a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2240a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2241a1cb98faSBarry Smith DMClone(dm, §iondm); 2242a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2243a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2244a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2245a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2246a1cb98faSBarry Smith PetscSectionSetUp(section); 2247a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2248a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2249a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2250a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2251a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2252a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2253a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2254a1cb98faSBarry Smith DMDestroy(§iondm); 2255a1cb98faSBarry Smith DMDestroy(&dm); 2256a1cb98faSBarry Smith .ve 22573e97647fSksagiyam 22581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22593e97647fSksagiyam @*/ 2260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2261d71ae5a4SJacob Faibussowitsch { 22623e97647fSksagiyam PetscBool ishdf5; 22633e97647fSksagiyam 22643e97647fSksagiyam PetscFunctionBegin; 22653e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22663e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22673e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22683e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22693e97647fSksagiyam /* Check consistency */ 22703e97647fSksagiyam { 22713e97647fSksagiyam PetscSection section; 22723e97647fSksagiyam PetscBool includesConstraints; 22733e97647fSksagiyam PetscInt m, m1; 22743e97647fSksagiyam 22759566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22789566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22799566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 228063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 22813e97647fSksagiyam } 22829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 22843e97647fSksagiyam if (ishdf5) { 22853e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22869566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22873e97647fSksagiyam #else 22883e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22893e97647fSksagiyam #endif 22903e97647fSksagiyam } 22919566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 22923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22933e97647fSksagiyam } 22943e97647fSksagiyam 2295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2296d71ae5a4SJacob Faibussowitsch { 2297d4f5a9a0SVaclav Hapla PetscBool ishdf5; 22982c40f234SMatthew G. Knepley 22992c40f234SMatthew G. Knepley PetscFunctionBegin; 23002c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23012c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2303d4f5a9a0SVaclav Hapla if (ishdf5) { 23042c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23059c48423bSVaclav Hapla PetscViewerFormat format; 23069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23079c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23089566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2309509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23109566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 231198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23132c40f234SMatthew G. Knepley #else 23142c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2315552f7358SJed Brown #endif 231698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2317552f7358SJed Brown } 2318552f7358SJed Brown 2319ea8e1828Sksagiyam /*@ 2320a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2321ea8e1828Sksagiyam 232220f4b53cSBarry Smith Collective 2323ea8e1828Sksagiyam 2324ea8e1828Sksagiyam Input Parameters: 2325a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2326a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2327ea8e1828Sksagiyam 23282fe279fdSBarry Smith Output Parameter: 232920f4b53cSBarry 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 2330dec9e869Sksagiyam 2331ea8e1828Sksagiyam Level: advanced 2332ea8e1828Sksagiyam 23331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2334a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2335ea8e1828Sksagiyam @*/ 2336d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2337d71ae5a4SJacob Faibussowitsch { 2338ea8e1828Sksagiyam PetscBool ishdf5; 2339ea8e1828Sksagiyam 2340ea8e1828Sksagiyam PetscFunctionBegin; 2341ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2342ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23434f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2346ea8e1828Sksagiyam if (ishdf5) { 2347ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2348ea8e1828Sksagiyam PetscViewerFormat format; 23499566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2350ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23519566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 235298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2353ea8e1828Sksagiyam #else 2354ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2355ea8e1828Sksagiyam #endif 2356ea8e1828Sksagiyam } 23579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2359ea8e1828Sksagiyam } 2360ea8e1828Sksagiyam 23613e701f1cSksagiyam /*@ 2362a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23633e701f1cSksagiyam 236420f4b53cSBarry Smith Collective 23653e701f1cSksagiyam 23663e701f1cSksagiyam Input Parameters: 2367a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2368a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2369a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23703e701f1cSksagiyam 23713e701f1cSksagiyam Level: advanced 23723e701f1cSksagiyam 23731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2374a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23753e701f1cSksagiyam @*/ 2376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2377d71ae5a4SJacob Faibussowitsch { 23783e701f1cSksagiyam PetscBool ishdf5; 23793e701f1cSksagiyam 23803e701f1cSksagiyam PetscFunctionBegin; 23813e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23823e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2383c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 23849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 23863e701f1cSksagiyam if (ishdf5) { 23873e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 23883e701f1cSksagiyam PetscViewerFormat format; 23899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23903e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23919566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 239298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23933e701f1cSksagiyam #else 23943e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23953e701f1cSksagiyam #endif 23963e701f1cSksagiyam } 23979566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 23983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23993e701f1cSksagiyam } 24003e701f1cSksagiyam 2401b08ad5deSksagiyam /*@ 2402a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2403b08ad5deSksagiyam 240420f4b53cSBarry Smith Collective 2405b08ad5deSksagiyam 2406b08ad5deSksagiyam Input Parameters: 2407a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2408a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 240920f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2410b08ad5deSksagiyam 2411b08ad5deSksagiyam Level: advanced 2412b08ad5deSksagiyam 2413a1cb98faSBarry Smith Note: 2414a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2415e6368b79SVaclav Hapla 24161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2417a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2418b08ad5deSksagiyam @*/ 2419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2420d71ae5a4SJacob Faibussowitsch { 2421b08ad5deSksagiyam PetscBool ishdf5; 2422b08ad5deSksagiyam 2423b08ad5deSksagiyam PetscFunctionBegin; 2424b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2425b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2426e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24289566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2429b08ad5deSksagiyam if (ishdf5) { 2430b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2431b08ad5deSksagiyam PetscViewerFormat format; 2432b08ad5deSksagiyam 24339566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2434b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24359566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 243698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2437b08ad5deSksagiyam #else 2438b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2439b08ad5deSksagiyam #endif 2440b08ad5deSksagiyam } 24419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2443b08ad5deSksagiyam } 2444b08ad5deSksagiyam 2445f84dd6b4Sksagiyam /*@ 2446a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2447f84dd6b4Sksagiyam 244820f4b53cSBarry Smith Collective 2449f84dd6b4Sksagiyam 2450f84dd6b4Sksagiyam Input Parameters: 2451a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2452a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 2453a1cb98faSBarry Smith . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated 2454a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2455f84dd6b4Sksagiyam 2456a4e35b19SJacob Faibussowitsch Output Parameters: 245720f4b53cSBarry 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) 245820f4b53cSBarry 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) 2459f84dd6b4Sksagiyam 2460f84dd6b4Sksagiyam Level: advanced 2461f84dd6b4Sksagiyam 2462f84dd6b4Sksagiyam Notes: 246320f4b53cSBarry 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. 2464f84dd6b4Sksagiyam 246520f4b53cSBarry Smith 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 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. 2466f84dd6b4Sksagiyam 246720f4b53cSBarry 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. 2468f84dd6b4Sksagiyam 2469f84dd6b4Sksagiyam Example using 2 processes: 2470a1cb98faSBarry Smith .vb 2471a1cb98faSBarry Smith NX (number of points on dm): 4 2472a1cb98faSBarry Smith sectionA : the on-disk section 2473a1cb98faSBarry Smith vecA : a vector associated with sectionA 2474a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2475a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2476a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2477f84dd6b4Sksagiyam 2478a1cb98faSBarry Smith rank 0 rank 1 2479a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2480a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2481a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2482a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2483a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2484a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2485a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2486a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2487a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2488a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2489a1cb98faSBarry Smith .ve 2490a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2491a1cb98faSBarry Smith 24921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2493f84dd6b4Sksagiyam @*/ 2494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2495d71ae5a4SJacob Faibussowitsch { 2496f84dd6b4Sksagiyam PetscBool ishdf5; 2497f84dd6b4Sksagiyam 2498f84dd6b4Sksagiyam PetscFunctionBegin; 2499f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2500f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2501f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2502f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25034f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25044f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2507f84dd6b4Sksagiyam if (ishdf5) { 2508f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25099566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2510f84dd6b4Sksagiyam #else 2511f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2512f84dd6b4Sksagiyam #endif 2513f84dd6b4Sksagiyam } 25149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2516f84dd6b4Sksagiyam } 2517f84dd6b4Sksagiyam 25188be3dfe1Sksagiyam /*@ 25198be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25208be3dfe1Sksagiyam 252120f4b53cSBarry Smith Collective 25228be3dfe1Sksagiyam 25238be3dfe1Sksagiyam Input Parameters: 2524a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2525a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2526a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 2527a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25288be3dfe1Sksagiyam - vec - The global vector to set values of 25298be3dfe1Sksagiyam 25308be3dfe1Sksagiyam Level: advanced 25318be3dfe1Sksagiyam 25328be3dfe1Sksagiyam Notes: 2533a1cb98faSBarry Smith 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 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. 25348be3dfe1Sksagiyam 253560225df5SJacob Faibussowitsch Calling sequence: 2536a1cb98faSBarry Smith .vb 2537a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2538a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2539a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2540a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2541a1cb98faSBarry Smith DMClone(dm, §iondm); 2542a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2543a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2544a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2545a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2546a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2547a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2548a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2549a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2550a1cb98faSBarry Smith DMDestroy(§iondm); 2551a1cb98faSBarry Smith DMDestroy(&dm); 2552a1cb98faSBarry Smith .ve 25538be3dfe1Sksagiyam 25541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2555a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25568be3dfe1Sksagiyam @*/ 2557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2558d71ae5a4SJacob Faibussowitsch { 25598be3dfe1Sksagiyam PetscBool ishdf5; 25608be3dfe1Sksagiyam 25618be3dfe1Sksagiyam PetscFunctionBegin; 25628be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25638be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25648be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25658be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25668be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25678be3dfe1Sksagiyam /* Check consistency */ 25688be3dfe1Sksagiyam { 25698be3dfe1Sksagiyam PetscSection section; 25708be3dfe1Sksagiyam PetscBool includesConstraints; 25718be3dfe1Sksagiyam PetscInt m, m1; 25728be3dfe1Sksagiyam 25739566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25769566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25779566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 257863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 25798be3dfe1Sksagiyam } 25809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 25828be3dfe1Sksagiyam if (ishdf5) { 25838be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 25849566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 25858be3dfe1Sksagiyam #else 25868be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25878be3dfe1Sksagiyam #endif 25888be3dfe1Sksagiyam } 25899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 25903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25918be3dfe1Sksagiyam } 25928be3dfe1Sksagiyam 25938be3dfe1Sksagiyam /*@ 25948be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 25958be3dfe1Sksagiyam 259620f4b53cSBarry Smith Collective 25978be3dfe1Sksagiyam 25988be3dfe1Sksagiyam Input Parameters: 2599a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2600a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2601a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined 2602a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26038be3dfe1Sksagiyam - vec - The local vector to set values of 26048be3dfe1Sksagiyam 26058be3dfe1Sksagiyam Level: advanced 26068be3dfe1Sksagiyam 26078be3dfe1Sksagiyam Notes: 260820f4b53cSBarry Smith 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 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. 26098be3dfe1Sksagiyam 261060225df5SJacob Faibussowitsch Calling sequence: 2611a1cb98faSBarry Smith .vb 2612a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2613a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2614a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2615a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2616a1cb98faSBarry Smith DMClone(dm, §iondm); 2617a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2618a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2619a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2620a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2621a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2622a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2623a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2624a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2625a1cb98faSBarry Smith DMDestroy(§iondm); 2626a1cb98faSBarry Smith DMDestroy(&dm); 2627a1cb98faSBarry Smith .ve 26288be3dfe1Sksagiyam 26291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2630a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26318be3dfe1Sksagiyam @*/ 2632d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2633d71ae5a4SJacob Faibussowitsch { 26348be3dfe1Sksagiyam PetscBool ishdf5; 26358be3dfe1Sksagiyam 26368be3dfe1Sksagiyam PetscFunctionBegin; 26378be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26388be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26398be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26408be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26418be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26428be3dfe1Sksagiyam /* Check consistency */ 26438be3dfe1Sksagiyam { 26448be3dfe1Sksagiyam PetscSection section; 26458be3dfe1Sksagiyam PetscBool includesConstraints; 26468be3dfe1Sksagiyam PetscInt m, m1; 26478be3dfe1Sksagiyam 26489566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26499566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26519566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26529566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 265363a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26548be3dfe1Sksagiyam } 26559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26578be3dfe1Sksagiyam if (ishdf5) { 26588be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26599566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26608be3dfe1Sksagiyam #else 26618be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26628be3dfe1Sksagiyam #endif 26638be3dfe1Sksagiyam } 26649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26668be3dfe1Sksagiyam } 26678be3dfe1Sksagiyam 2668d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2669d71ae5a4SJacob Faibussowitsch { 2670552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2671552f7358SJed Brown 2672552f7358SJed Brown PetscFunctionBegin; 26739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26776c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 26782e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 26792e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 26802e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 26812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 26826bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 26836bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2684c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2685c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2686d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2687d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 26885f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 26893ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 26909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 26919566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 26929566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 26939566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 26949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 26959566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 269621027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 26979f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 26989566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 26999566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27009566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27011d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27029566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27039566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27074e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27086725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27096725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27129566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27139566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27149566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27179566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27189566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27199566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27209566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2721552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27229566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2724552f7358SJed Brown } 2725552f7358SJed Brown 2726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2727d71ae5a4SJacob Faibussowitsch { 27288d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2729acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27309fca9976SJed Brown PetscInt localSize, localStart = 0; 2731837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2732b412c318SBarry Smith MatType mtype; 27331428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2734552f7358SJed Brown 2735552f7358SJed Brown PetscFunctionBegin; 27369566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2737b412c318SBarry Smith mtype = dm->mattype; 27389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27399566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27419fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27429566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27439566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27449566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27459566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27469566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2747acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27529566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27549566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27559566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2756552f7358SJed Brown if (!isShell) { 2757837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27589fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2759863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2760552f7358SJed Brown 27619566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27629fca9976SJed Brown 27639fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2765863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2766e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2767863027abSJed Brown switch (dm->blocking_type) { 27680e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27699fca9976SJed Brown PetscInt bdof, offset; 2770a9d99c84SMatthew G. Knepley 27719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27729fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 27739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 27749371c9d4SSatish Balay for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof; 27751d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 27761d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 27771d17a0a3SMatthew G. Knepley if (dof) { 27789371c9d4SSatish Balay if (bs < 0) { 27799371c9d4SSatish Balay bs = bdof; 27809371c9d4SSatish Balay } else if (bs != bdof) { 27819371c9d4SSatish Balay bs = 1; 27829371c9d4SSatish Balay } 2783552f7358SJed Brown } 2784863027abSJed Brown } break; 2785863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2786863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2787863027abSJed Brown PetscInt num_comp, bdof, offset; 2788863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2789863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2790863027abSJed Brown if (dof < 0) continue; 2791863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2792863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2793863027abSJed 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); 2794863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2795863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2796863027abSJed Brown // Handle possibly constant block size (unlikely) 2797863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2798863027abSJed Brown if (dof) { 2799863027abSJed Brown if (bs < 0) { 2800863027abSJed Brown bs = bdof; 2801863027abSJed Brown } else if (bs != bdof) { 2802863027abSJed Brown bs = 1; 2803863027abSJed Brown } 2804863027abSJed Brown } 2805863027abSJed Brown } 2806863027abSJed Brown } break; 2807863027abSJed Brown } 28082a28c762SMatthew G Knepley } 28092a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2810e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2811e432b41dSStefano Zampini bsLocal[1] = bs; 28129566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2813e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2814e432b41dSStefano Zampini else bs = bsMinMax[0]; 28156fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28169566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28170682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28189566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28199566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28200682b8bbSJed Brown } else { 28219566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28229566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28239566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2824552f7358SJed Brown } 28259fca9976SJed Brown { // Consolidate blocks 28269fca9976SJed Brown PetscInt nblocks = 0; 28279fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28289fca9976SJed Brown if (pblocks[i] == 0) continue; 28299fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2830ad540459SPierre 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]); 28319fca9976SJed Brown } 28329fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28339fca9976SJed Brown } 28349fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2835aa0f6e3cSJed Brown } 28369566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2838552f7358SJed Brown } 2839552f7358SJed Brown 28407cd05799SMatthew G. Knepley /*@ 2841a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2842be36d101SStefano Zampini 2843a1cb98faSBarry Smith Not Collective 2844be36d101SStefano Zampini 2845be36d101SStefano Zampini Input Parameter: 284660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2847be36d101SStefano Zampini 28482fe279fdSBarry Smith Output Parameter: 2849be36d101SStefano Zampini . subsection - The subdomain section 2850be36d101SStefano Zampini 2851be36d101SStefano Zampini Level: developer 2852be36d101SStefano Zampini 28531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28547cd05799SMatthew G. Knepley @*/ 2855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2856d71ae5a4SJacob Faibussowitsch { 2857be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2858be36d101SStefano Zampini 2859be36d101SStefano Zampini PetscFunctionBegin; 2860be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2861be36d101SStefano Zampini if (!mesh->subdomainSection) { 2862be36d101SStefano Zampini PetscSection section; 2863be36d101SStefano Zampini PetscSF sf; 2864be36d101SStefano Zampini 28659566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 28669566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 28679566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 28689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2869be36d101SStefano Zampini } 2870be36d101SStefano Zampini *subsection = mesh->subdomainSection; 28713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2872be36d101SStefano Zampini } 2873be36d101SStefano Zampini 2874552f7358SJed Brown /*@ 287520f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2876552f7358SJed Brown 2877a1cb98faSBarry Smith Not Collective 2878552f7358SJed Brown 2879552f7358SJed Brown Input Parameter: 288060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2881552f7358SJed Brown 2882552f7358SJed Brown Output Parameters: 2883552f7358SJed Brown + pStart - The first mesh point 2884552f7358SJed Brown - pEnd - The upper bound for mesh points 2885552f7358SJed Brown 2886552f7358SJed Brown Level: beginner 2887552f7358SJed Brown 28881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2889552f7358SJed Brown @*/ 2890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2891d71ae5a4SJacob Faibussowitsch { 2892552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2893552f7358SJed Brown 2894552f7358SJed Brown PetscFunctionBegin; 2895552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28969f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 28979f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 28983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2899552f7358SJed Brown } 2900552f7358SJed Brown 2901552f7358SJed Brown /*@ 290220f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2903552f7358SJed Brown 2904a1cb98faSBarry Smith Not Collective 2905552f7358SJed Brown 2906552f7358SJed Brown Input Parameters: 290760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2908552f7358SJed Brown . pStart - The first mesh point 2909552f7358SJed Brown - pEnd - The upper bound for mesh points 2910552f7358SJed Brown 2911552f7358SJed Brown Level: beginner 2912552f7358SJed Brown 29131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2914552f7358SJed Brown @*/ 2915d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2916d71ae5a4SJacob Faibussowitsch { 2917552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2918552f7358SJed Brown 2919552f7358SJed Brown PetscFunctionBegin; 2920552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 292321027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2925552f7358SJed Brown } 2926552f7358SJed Brown 2927552f7358SJed Brown /*@ 2928eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2929552f7358SJed Brown 2930a1cb98faSBarry Smith Not Collective 2931552f7358SJed Brown 2932552f7358SJed Brown Input Parameters: 293360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2934a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2935552f7358SJed Brown 2936552f7358SJed Brown Output Parameter: 293720f4b53cSBarry Smith . size - The cone size for point `p` 2938552f7358SJed Brown 2939552f7358SJed Brown Level: beginner 2940552f7358SJed Brown 29411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2942552f7358SJed Brown @*/ 2943d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2944d71ae5a4SJacob Faibussowitsch { 2945552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2946552f7358SJed Brown 2947552f7358SJed Brown PetscFunctionBegin; 2948552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29494f572ea9SToby Isaac PetscAssertPointer(size, 3); 29509f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29519f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2953552f7358SJed Brown } 2954552f7358SJed Brown 2955552f7358SJed Brown /*@ 2956eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2957552f7358SJed Brown 2958a1cb98faSBarry Smith Not Collective 2959552f7358SJed Brown 2960552f7358SJed Brown Input Parameters: 296160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2962a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 296320f4b53cSBarry Smith - size - The cone size for point `p` 2964552f7358SJed Brown 2965552f7358SJed Brown Level: beginner 2966552f7358SJed Brown 2967a1cb98faSBarry Smith Note: 2968a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 2969a1cb98faSBarry Smith 29701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2971552f7358SJed Brown @*/ 2972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2973d71ae5a4SJacob Faibussowitsch { 2974552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2975552f7358SJed Brown 2976552f7358SJed Brown PetscFunctionBegin; 2977552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29789f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 29799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 29803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2981552f7358SJed Brown } 2982552f7358SJed Brown 2983552f7358SJed Brown /*@C 2984eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2985552f7358SJed Brown 2986a1cb98faSBarry Smith Not Collective 2987552f7358SJed Brown 2988552f7358SJed Brown Input Parameters: 2989a1cb98faSBarry Smith + dm - The `DMPLEX` 2990a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2991552f7358SJed Brown 2992552f7358SJed Brown Output Parameter: 299320f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 2994552f7358SJed Brown 2995552f7358SJed Brown Level: beginner 2996552f7358SJed Brown 299760225df5SJacob Faibussowitsch Fortran Notes: 2998a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 2999a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30003813dfbdSMatthew G Knepley 30011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3002552f7358SJed Brown @*/ 3003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3004d71ae5a4SJacob Faibussowitsch { 3005552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3006552f7358SJed Brown PetscInt off; 3007552f7358SJed Brown 3008552f7358SJed Brown PetscFunctionBegin; 3009552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30104f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3012552f7358SJed Brown *cone = &mesh->cones[off]; 30133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3014552f7358SJed Brown } 3015552f7358SJed Brown 30160ce7577fSVaclav Hapla /*@C 30170ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30180ce7577fSVaclav Hapla 3019a1cb98faSBarry Smith Not Collective 30200ce7577fSVaclav Hapla 30210ce7577fSVaclav Hapla Input Parameters: 3022a1cb98faSBarry Smith + dm - The `DMPLEX` 3023a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30240ce7577fSVaclav Hapla 3025d8d19677SJose E. Roman Output Parameters: 302620f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 302720f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30280ce7577fSVaclav Hapla 30290ce7577fSVaclav Hapla Level: intermediate 30300ce7577fSVaclav Hapla 30311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30320ce7577fSVaclav Hapla @*/ 3033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3034d71ae5a4SJacob Faibussowitsch { 30350ce7577fSVaclav Hapla PetscSection cs, newcs; 30360ce7577fSVaclav Hapla PetscInt *cones; 30370ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30380ce7577fSVaclav Hapla PetscInt n; 30390ce7577fSVaclav Hapla 30400ce7577fSVaclav Hapla PetscFunctionBegin; 30419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30439566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30440ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30450ce7577fSVaclav Hapla if (pCones) { 30469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30480ce7577fSVaclav Hapla } 30493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30500ce7577fSVaclav Hapla } 30510ce7577fSVaclav Hapla 3052af9eab45SVaclav Hapla /*@ 3053af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3054d4636a37SVaclav Hapla 3055a1cb98faSBarry Smith Not Collective 3056d4636a37SVaclav Hapla 3057d4636a37SVaclav Hapla Input Parameters: 3058a1cb98faSBarry Smith + dm - The `DMPLEX` 3059a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3060d4636a37SVaclav Hapla 3061d4636a37SVaclav Hapla Output Parameter: 3062af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3063d4636a37SVaclav Hapla 3064d4636a37SVaclav Hapla Level: advanced 3065d4636a37SVaclav Hapla 3066af9eab45SVaclav Hapla Notes: 306720f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3068af9eab45SVaclav Hapla 3069a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3070a1cb98faSBarry Smith 30711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3072a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3073d4636a37SVaclav Hapla @*/ 3074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3075d71ae5a4SJacob Faibussowitsch { 3076af9eab45SVaclav Hapla IS *expandedPointsAll; 3077af9eab45SVaclav Hapla PetscInt depth; 3078d4636a37SVaclav Hapla 3079d4636a37SVaclav Hapla PetscFunctionBegin; 3080af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3081af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 30824f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 30839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3084af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 30859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 30869566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 30873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3088af9eab45SVaclav Hapla } 3089af9eab45SVaclav Hapla 3090af9eab45SVaclav Hapla /*@ 3091af9eab45SVaclav 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). 3092af9eab45SVaclav Hapla 3093a1cb98faSBarry Smith Not Collective 3094af9eab45SVaclav Hapla 3095af9eab45SVaclav Hapla Input Parameters: 3096a1cb98faSBarry Smith + dm - The `DMPLEX` 3097a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3098af9eab45SVaclav Hapla 3099d8d19677SJose E. Roman Output Parameters: 3100a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3101af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3102af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3103af9eab45SVaclav Hapla 3104af9eab45SVaclav Hapla Level: advanced 3105af9eab45SVaclav Hapla 3106af9eab45SVaclav Hapla Notes: 3107a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3108af9eab45SVaclav Hapla 3109a4e35b19SJacob 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. 3110af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3111af9eab45SVaclav Hapla 3112a4e35b19SJacob 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\: 3113a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3114a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3115af9eab45SVaclav Hapla 31161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3117a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3118af9eab45SVaclav Hapla @*/ 3119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3120d71ae5a4SJacob Faibussowitsch { 3121af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3122af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3123af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3124af9eab45SVaclav Hapla IS *expandedPoints_; 3125af9eab45SVaclav Hapla PetscSection *sections_; 3126af9eab45SVaclav Hapla 3127af9eab45SVaclav Hapla PetscFunctionBegin; 3128af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3129af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31304f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31314f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31324f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31369566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3138af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3139af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31409566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3142af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3144af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31459566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3147af9eab45SVaclav Hapla } else { 31489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3149af9eab45SVaclav Hapla } 3150af9eab45SVaclav Hapla } 31519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3154af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3157af9eab45SVaclav Hapla if (cn > 1) { 31589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31599566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3160af9eab45SVaclav Hapla } else { 3161af9eab45SVaclav Hapla newarr[co] = arr[i]; 3162af9eab45SVaclav Hapla } 3163af9eab45SVaclav Hapla } 31649566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3165af9eab45SVaclav Hapla arr = newarr; 3166af9eab45SVaclav Hapla n = newn; 3167af9eab45SVaclav Hapla } 31689566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3169af9eab45SVaclav Hapla *depth = depth_; 3170af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3171af9eab45SVaclav Hapla else { 31729566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 31739566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3174af9eab45SVaclav Hapla } 3175af9eab45SVaclav Hapla if (sections) *sections = sections_; 3176af9eab45SVaclav Hapla else { 31779566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 31789566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3179af9eab45SVaclav Hapla } 31803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3181af9eab45SVaclav Hapla } 3182af9eab45SVaclav Hapla 3183af9eab45SVaclav Hapla /*@ 3184a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3185af9eab45SVaclav Hapla 3186a1cb98faSBarry Smith Not Collective 3187af9eab45SVaclav Hapla 3188af9eab45SVaclav Hapla Input Parameters: 3189a1cb98faSBarry Smith + dm - The `DMPLEX` 3190a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3191af9eab45SVaclav Hapla 3192d8d19677SJose E. Roman Output Parameters: 3193a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3194af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3195af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3196af9eab45SVaclav Hapla 3197af9eab45SVaclav Hapla Level: advanced 3198af9eab45SVaclav Hapla 3199a1cb98faSBarry Smith Note: 3200a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3201af9eab45SVaclav Hapla 32021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3203a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3204af9eab45SVaclav Hapla @*/ 3205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3206d71ae5a4SJacob Faibussowitsch { 3207af9eab45SVaclav Hapla PetscInt d, depth_; 3208af9eab45SVaclav Hapla 3209af9eab45SVaclav Hapla PetscFunctionBegin; 32109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32111dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3212af9eab45SVaclav Hapla if (depth) *depth = 0; 3213af9eab45SVaclav Hapla if (expandedPoints) { 32149566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32159566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3216af9eab45SVaclav Hapla } 3217af9eab45SVaclav Hapla if (sections) { 32189566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32199566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3220af9eab45SVaclav Hapla } 32213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3222d4636a37SVaclav Hapla } 3223d4636a37SVaclav Hapla 3224552f7358SJed Brown /*@ 322592371b87SBarry 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 3226552f7358SJed Brown 3227a1cb98faSBarry Smith Not Collective 3228552f7358SJed Brown 3229552f7358SJed Brown Input Parameters: 323060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3231a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 323220f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3233552f7358SJed Brown 3234552f7358SJed Brown Level: beginner 3235552f7358SJed Brown 3236a1cb98faSBarry Smith Note: 3237a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3238a1cb98faSBarry Smith 32391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3240552f7358SJed Brown @*/ 3241d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3242d71ae5a4SJacob Faibussowitsch { 3243552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3244552f7358SJed Brown PetscInt dof, off, c; 3245552f7358SJed Brown 3246552f7358SJed Brown PetscFunctionBegin; 3247552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32494f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3251db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3252db485b19SStefano Zampini PetscInt pStart, pEnd; 3253db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 325463a3b9bcSJacob 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); 3255552f7358SJed Brown for (c = 0; c < dof; ++c) { 325663a3b9bcSJacob 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); 3257552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3258552f7358SJed Brown } 3259db485b19SStefano Zampini } else { 3260db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3261db485b19SStefano Zampini } 32623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3263552f7358SJed Brown } 3264552f7358SJed Brown 3265552f7358SJed Brown /*@C 3266eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3267552f7358SJed Brown 3268a1cb98faSBarry Smith Not Collective 3269552f7358SJed Brown 3270552f7358SJed Brown Input Parameters: 327160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3272a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3273552f7358SJed Brown 3274552f7358SJed Brown Output Parameter: 327520f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3276b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3277552f7358SJed Brown 3278552f7358SJed Brown Level: beginner 3279552f7358SJed Brown 3280a1cb98faSBarry Smith Note: 3281b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3282b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3283a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3284b5a892a1SMatthew G. Knepley with the identity. 3285b5a892a1SMatthew G. Knepley 328660225df5SJacob Faibussowitsch Fortran Notes: 3287a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3288a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 32893813dfbdSMatthew G Knepley 32901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3291552f7358SJed Brown @*/ 3292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3293d71ae5a4SJacob Faibussowitsch { 3294552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3295552f7358SJed Brown PetscInt off; 3296552f7358SJed Brown 3297552f7358SJed Brown PetscFunctionBegin; 3298552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 329976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3300552f7358SJed Brown PetscInt dof; 33019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33024f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3303552f7358SJed Brown } 33049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33050d644c17SKarl Rupp 3306552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3308552f7358SJed Brown } 3309552f7358SJed Brown 3310552f7358SJed Brown /*@ 3311eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3312552f7358SJed Brown 3313a1cb98faSBarry Smith Not Collective 3314552f7358SJed Brown 3315552f7358SJed Brown Input Parameters: 331660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3317a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3318b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3319b5a892a1SMatthew G. Knepley 3320552f7358SJed Brown Level: beginner 3321552f7358SJed Brown 3322a1cb98faSBarry Smith Notes: 3323a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3324a1cb98faSBarry Smith 3325a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3326a1cb98faSBarry Smith 33271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3328552f7358SJed Brown @*/ 3329d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3330d71ae5a4SJacob Faibussowitsch { 3331552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3332552f7358SJed Brown PetscInt pStart, pEnd; 3333552f7358SJed Brown PetscInt dof, off, c; 3334552f7358SJed Brown 3335552f7358SJed Brown PetscFunctionBegin; 3336552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33384f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3340db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3341db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 334263a3b9bcSJacob 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); 3343552f7358SJed Brown for (c = 0; c < dof; ++c) { 3344552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3345552f7358SJed Brown 33469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33471dca8a05SBarry 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); 3348552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3349552f7358SJed Brown } 3350db485b19SStefano Zampini } else { 3351db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3352db485b19SStefano Zampini } 33533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3354552f7358SJed Brown } 3355552f7358SJed Brown 33567cd05799SMatthew G. Knepley /*@ 3357eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33587cd05799SMatthew G. Knepley 3359a1cb98faSBarry Smith Not Collective 33607cd05799SMatthew G. Knepley 33617cd05799SMatthew G. Knepley Input Parameters: 336260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3363a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33647cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 33657cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 33667cd05799SMatthew G. Knepley 33677cd05799SMatthew G. Knepley Level: beginner 33687cd05799SMatthew G. Knepley 33691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33707cd05799SMatthew G. Knepley @*/ 3371d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3372d71ae5a4SJacob Faibussowitsch { 3373552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3374552f7358SJed Brown PetscInt pStart, pEnd; 3375552f7358SJed Brown PetscInt dof, off; 3376552f7358SJed Brown 3377552f7358SJed Brown PetscFunctionBegin; 3378552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3379a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 33809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 338163a3b9bcSJacob 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); 338263a3b9bcSJacob 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); 33839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 338463a3b9bcSJacob 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); 3385a03d55ffSStefano Zampini } 3386a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3387552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 33883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3389552f7358SJed Brown } 3390552f7358SJed Brown 33917cd05799SMatthew G. Knepley /*@ 3392eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 33937cd05799SMatthew G. Knepley 3394a1cb98faSBarry Smith Not Collective 33957cd05799SMatthew G. Knepley 33967cd05799SMatthew G. Knepley Input Parameters: 339760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3398a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33997cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34007cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34017cd05799SMatthew G. Knepley 34027cd05799SMatthew G. Knepley Level: beginner 34037cd05799SMatthew G. Knepley 3404a1cb98faSBarry Smith Note: 3405a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3406b5a892a1SMatthew G. Knepley 34071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34087cd05799SMatthew G. Knepley @*/ 3409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3410d71ae5a4SJacob Faibussowitsch { 341177c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 341277c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 341377c88f5bSMatthew G Knepley PetscInt dof, off; 341477c88f5bSMatthew G Knepley 341577c88f5bSMatthew G Knepley PetscFunctionBegin; 341677c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3417a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 341963a3b9bcSJacob 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); 34209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 342163a3b9bcSJacob 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); 3422a03d55ffSStefano Zampini } 3423a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 342477c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 342677c88f5bSMatthew G Knepley } 342777c88f5bSMatthew G Knepley 34289f4ada15SMatthew G. Knepley /*@C 34299f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34309f4ada15SMatthew G. Knepley 34319f4ada15SMatthew G. Knepley Not collective 34329f4ada15SMatthew G. Knepley 34339f4ada15SMatthew G. Knepley Input Parameters: 34349f4ada15SMatthew G. Knepley + dm - The DMPlex 34359f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34369f4ada15SMatthew G. Knepley 34379f4ada15SMatthew G. Knepley Output Parameters: 343820f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 343920f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34409f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34419f4ada15SMatthew G. Knepley 34429f4ada15SMatthew G. Knepley Level: beginner 34439f4ada15SMatthew G. Knepley 34449f4ada15SMatthew G. Knepley Notes: 34459f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34469f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 344720f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34489f4ada15SMatthew G. Knepley with the identity. 34499f4ada15SMatthew G. Knepley 34509f4ada15SMatthew G. Knepley Fortran Notes: 345120f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 345220f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34539f4ada15SMatthew G. Knepley 34541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34559f4ada15SMatthew G. Knepley @*/ 34569f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34579f4ada15SMatthew G. Knepley { 34589f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34599f4ada15SMatthew G. Knepley 34609f4ada15SMatthew G. Knepley PetscFunctionBegin; 34619f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34629f4ada15SMatthew G. Knepley if (mesh->tr) { 34639f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34649f4ada15SMatthew G. Knepley } else { 34659f4ada15SMatthew G. Knepley PetscInt off; 34669f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 34679f4ada15SMatthew G. Knepley PetscInt dof; 34689f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34699f4ada15SMatthew G. Knepley if (dof) { 34704f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 34714f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 34729f4ada15SMatthew G. Knepley } 34739f4ada15SMatthew G. Knepley } 34749f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3475072f5ffdSStefano Zampini if (cone) *cone = mesh->cones ? mesh->cones + off : NULL; // NULL + 0 is UB 3476072f5ffdSStefano Zampini if (ornt) *ornt = mesh->coneOrientations ? mesh->coneOrientations + off : NULL; 34779f4ada15SMatthew G. Knepley } 34783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34799f4ada15SMatthew G. Knepley } 34809f4ada15SMatthew G. Knepley 34819f4ada15SMatthew G. Knepley /*@C 34829f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 34839f4ada15SMatthew G. Knepley 348420f4b53cSBarry Smith Not Collective 34859f4ada15SMatthew G. Knepley 34869f4ada15SMatthew G. Knepley Input Parameters: 34879f4ada15SMatthew G. Knepley + dm - The DMPlex 348820f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34899f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 349020f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34919f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34929f4ada15SMatthew G. Knepley 34939f4ada15SMatthew G. Knepley Level: beginner 34949f4ada15SMatthew G. Knepley 34959f4ada15SMatthew G. Knepley Notes: 34969f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34979f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 349820f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34999f4ada15SMatthew G. Knepley with the identity. 35009f4ada15SMatthew G. Knepley 350160225df5SJacob Faibussowitsch Fortran Notes: 350220f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 350320f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35049f4ada15SMatthew G. Knepley 35051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35069f4ada15SMatthew G. Knepley @*/ 35079f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35089f4ada15SMatthew G. Knepley { 35099f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35109f4ada15SMatthew G. Knepley 35119f4ada15SMatthew G. Knepley PetscFunctionBegin; 35129f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35139f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35159f4ada15SMatthew G. Knepley } 35169f4ada15SMatthew G. Knepley 3517552f7358SJed Brown /*@ 3518eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3519552f7358SJed Brown 3520a1cb98faSBarry Smith Not Collective 3521552f7358SJed Brown 3522552f7358SJed Brown Input Parameters: 352360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3524a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3525552f7358SJed Brown 3526552f7358SJed Brown Output Parameter: 352720f4b53cSBarry Smith . size - The support size for point `p` 3528552f7358SJed Brown 3529552f7358SJed Brown Level: beginner 3530552f7358SJed Brown 35311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3532552f7358SJed Brown @*/ 3533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3534d71ae5a4SJacob Faibussowitsch { 3535552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3536552f7358SJed Brown 3537552f7358SJed Brown PetscFunctionBegin; 3538552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35394f572ea9SToby Isaac PetscAssertPointer(size, 3); 35409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3542552f7358SJed Brown } 3543552f7358SJed Brown 3544552f7358SJed Brown /*@ 3545eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3546552f7358SJed Brown 3547a1cb98faSBarry Smith Not Collective 3548552f7358SJed Brown 3549552f7358SJed Brown Input Parameters: 355060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3551a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 355220f4b53cSBarry Smith - size - The support size for point `p` 3553552f7358SJed Brown 3554a1cb98faSBarry Smith Level: beginner 3555552f7358SJed Brown 3556552f7358SJed Brown Note: 355720f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3558552f7358SJed Brown 35591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3560552f7358SJed Brown @*/ 3561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3562d71ae5a4SJacob Faibussowitsch { 3563552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3564552f7358SJed Brown 3565552f7358SJed Brown PetscFunctionBegin; 3566552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 35683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3569552f7358SJed Brown } 3570552f7358SJed Brown 3571552f7358SJed Brown /*@C 3572eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3573552f7358SJed Brown 3574a1cb98faSBarry Smith Not Collective 3575552f7358SJed Brown 3576552f7358SJed Brown Input Parameters: 357760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3578a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3579552f7358SJed Brown 3580552f7358SJed Brown Output Parameter: 358120f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3582552f7358SJed Brown 3583552f7358SJed Brown Level: beginner 3584552f7358SJed Brown 358560225df5SJacob Faibussowitsch Fortran Notes: 3586a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3587a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 35883813dfbdSMatthew G Knepley 35891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3590552f7358SJed Brown @*/ 3591d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3592d71ae5a4SJacob Faibussowitsch { 3593552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3594552f7358SJed Brown PetscInt off; 3595552f7358SJed Brown 3596552f7358SJed Brown PetscFunctionBegin; 3597552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35984f572ea9SToby Isaac PetscAssertPointer(support, 3); 35999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3600072f5ffdSStefano Zampini *support = mesh->supports ? mesh->supports + off : NULL; //NULL + 0 is UB 36013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3602552f7358SJed Brown } 3603552f7358SJed Brown 3604552f7358SJed Brown /*@ 360592371b87SBarry 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 3606552f7358SJed Brown 3607a1cb98faSBarry Smith Not Collective 3608552f7358SJed Brown 3609552f7358SJed Brown Input Parameters: 361060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3611a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 361220f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3613552f7358SJed Brown 3614552f7358SJed Brown Level: beginner 3615552f7358SJed Brown 3616a1cb98faSBarry Smith Note: 3617a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3618a1cb98faSBarry Smith 36191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3620552f7358SJed Brown @*/ 3621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3622d71ae5a4SJacob Faibussowitsch { 3623552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3624552f7358SJed Brown PetscInt pStart, pEnd; 3625552f7358SJed Brown PetscInt dof, off, c; 3626552f7358SJed Brown 3627552f7358SJed Brown PetscFunctionBegin; 3628552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36314f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 363363a3b9bcSJacob 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); 3634552f7358SJed Brown for (c = 0; c < dof; ++c) { 363563a3b9bcSJacob 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); 3636552f7358SJed Brown mesh->supports[off + c] = support[c]; 3637552f7358SJed Brown } 36383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3639552f7358SJed Brown } 3640552f7358SJed Brown 36417cd05799SMatthew G. Knepley /*@ 3642eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36437cd05799SMatthew G. Knepley 3644a1cb98faSBarry Smith Not Collective 36457cd05799SMatthew G. Knepley 36467cd05799SMatthew G. Knepley Input Parameters: 364760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3648a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36497cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36507cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36517cd05799SMatthew G. Knepley 36527cd05799SMatthew G. Knepley Level: beginner 36537cd05799SMatthew G. Knepley 36541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36557cd05799SMatthew G. Knepley @*/ 3656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3657d71ae5a4SJacob Faibussowitsch { 3658552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3659552f7358SJed Brown PetscInt pStart, pEnd; 3660552f7358SJed Brown PetscInt dof, off; 3661552f7358SJed Brown 3662552f7358SJed Brown PetscFunctionBegin; 3663552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 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); 366863a3b9bcSJacob 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); 366963a3b9bcSJacob 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); 3670552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 36713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3672552f7358SJed Brown } 3673552f7358SJed Brown 3674b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3675d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3676d71ae5a4SJacob Faibussowitsch { 3677b5a892a1SMatthew G. Knepley switch (ct) { 3678b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3679b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3680b5a892a1SMatthew G. Knepley break; 3681b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3682b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3683b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3684b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3685b5a892a1SMatthew G. Knepley break; 3686b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3687b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3688b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3689b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3690b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3691b5a892a1SMatthew G. Knepley break; 3692d71ae5a4SJacob Faibussowitsch default: 3693d71ae5a4SJacob Faibussowitsch return o; 3694b5a892a1SMatthew G. Knepley } 3695b5a892a1SMatthew G. Knepley return o; 3696b5a892a1SMatthew G. Knepley } 3697b5a892a1SMatthew G. Knepley 3698b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3699d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3700d71ae5a4SJacob Faibussowitsch { 3701b5a892a1SMatthew G. Knepley switch (ct) { 3702b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3703b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3704b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3705b5a892a1SMatthew G. Knepley break; 3706b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3707b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3708b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3709b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3710b5a892a1SMatthew G. Knepley break; 3711b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3712b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3713b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3714b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3715b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3716b5a892a1SMatthew G. Knepley break; 3717d71ae5a4SJacob Faibussowitsch default: 3718d71ae5a4SJacob Faibussowitsch return o; 3719b5a892a1SMatthew G. Knepley } 3720b5a892a1SMatthew G. Knepley return o; 3721b5a892a1SMatthew G. Knepley } 3722b5a892a1SMatthew G. Knepley 3723b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3724d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3725d71ae5a4SJacob Faibussowitsch { 3726b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3727b5a892a1SMatthew G. Knepley 3728b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3730b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3731b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3732b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3733b5a892a1SMatthew G. Knepley 37349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3737b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3738b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3739b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3740b5a892a1SMatthew G. Knepley 37419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3742b5a892a1SMatthew G. Knepley switch (ct) { 3743b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37449566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37459566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3746b5a892a1SMatthew G. Knepley break; 3747b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37489566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37499566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37509566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3751b5a892a1SMatthew G. Knepley break; 3752b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37539566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37549566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37559566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37569566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3757b5a892a1SMatthew G. Knepley break; 3758d71ae5a4SJacob Faibussowitsch default: 3759d71ae5a4SJacob Faibussowitsch break; 3760b5a892a1SMatthew G. Knepley } 3761b5a892a1SMatthew G. Knepley } 3762b5a892a1SMatthew G. Knepley } 37633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3764b5a892a1SMatthew G. Knepley } 3765b5a892a1SMatthew G. Knepley 376609015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 376709015e70SStefano Zampini { 376809015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 376909015e70SStefano Zampini 377009015e70SStefano Zampini PetscFunctionBeginHot; 377109015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 377209015e70SStefano Zampini if (useCone) { 377309015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 377409015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 377509015e70SStefano Zampini } else { 377609015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 377709015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 377809015e70SStefano Zampini } 377909015e70SStefano Zampini } else { 378009015e70SStefano Zampini if (useCone) { 378109015e70SStefano Zampini const PetscSection s = mesh->coneSection; 378209015e70SStefano Zampini const PetscInt ps = p - s->pStart; 378309015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 378409015e70SStefano Zampini 378509015e70SStefano Zampini *size = s->atlasDof[ps]; 378609015e70SStefano Zampini *arr = mesh->cones + off; 378709015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 378809015e70SStefano Zampini } else { 378909015e70SStefano Zampini const PetscSection s = mesh->supportSection; 379009015e70SStefano Zampini const PetscInt ps = p - s->pStart; 379109015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 379209015e70SStefano Zampini 379309015e70SStefano Zampini *size = s->atlasDof[ps]; 379409015e70SStefano Zampini *arr = mesh->supports + off; 379509015e70SStefano Zampini } 379609015e70SStefano Zampini } 379709015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 379809015e70SStefano Zampini } 379909015e70SStefano Zampini 380009015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_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) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 380709015e70SStefano Zampini } 380809015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 380909015e70SStefano Zampini } 381009015e70SStefano Zampini 3811d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3812d71ae5a4SJacob Faibussowitsch { 3813b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3814b5a892a1SMatthew G. Knepley PetscInt *closure; 3815b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3816b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3817b5a892a1SMatthew G. Knepley 3818b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3819b5a892a1SMatthew G. Knepley if (ornt) { 38209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3821476787b7SMatthew 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; 3822b5a892a1SMatthew G. Knepley } 3823b5a892a1SMatthew G. Knepley if (*points) { 3824b5a892a1SMatthew G. Knepley closure = *points; 3825b5a892a1SMatthew G. Knepley } else { 3826b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38279566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38289566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3829b5a892a1SMatthew G. Knepley } 383009015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3831b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3832b5a892a1SMatthew G. Knepley closure[off++] = p; 3833b5a892a1SMatthew G. Knepley closure[off++] = 0; 3834b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3835b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3836b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3837b5a892a1SMatthew G. Knepley } 3838b5a892a1SMatthew G. Knepley } else { 38395f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3840b5a892a1SMatthew G. Knepley 3841b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3842b5a892a1SMatthew G. Knepley closure[off++] = p; 3843b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3844b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3845b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3846b5a892a1SMatthew G. Knepley 38479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3848b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3849b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3850b5a892a1SMatthew G. Knepley } 3851b5a892a1SMatthew G. Knepley } 385209015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3853b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3854b5a892a1SMatthew G. Knepley if (points) *points = closure; 38553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3856b5a892a1SMatthew G. Knepley } 3857b5a892a1SMatthew G. Knepley 3858d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3859d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3860d71ae5a4SJacob Faibussowitsch { 3861b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3862b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3863b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3864b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3865b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3866b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3867b5a892a1SMatthew G. Knepley 3868b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 38699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 387009015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 38719566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3872b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3873b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3874b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 38759371c9d4SSatish Balay if (*points) { 38769371c9d4SSatish Balay pts = *points; 38779371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3878b5a892a1SMatthew G. Knepley c = 0; 3879b5a892a1SMatthew G. Knepley pts[c++] = point; 3880b5a892a1SMatthew G. Knepley pts[c++] = o; 38819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 38829566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 38839371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 38849371c9d4SSatish Balay pts[c++] = closure[cl]; 38859371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 38869371c9d4SSatish Balay } 38879566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 38889371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 38899371c9d4SSatish Balay pts[c++] = closure[cl]; 38909371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 38919371c9d4SSatish Balay } 38929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3893b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 38949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3895b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3896b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3897b5a892a1SMatthew G. Knepley } 389809015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3899b5a892a1SMatthew G. Knepley if (dim >= 3) { 3900b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3901b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3902b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3903b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3904b5a892a1SMatthew G. Knepley 39059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3906b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 390709015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3908b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3909b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3910b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3911b5a892a1SMatthew G. Knepley 39129371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39139371c9d4SSatish Balay if (pts[i] == cp) break; 3914b5a892a1SMatthew G. Knepley if (i == c) { 39159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3916b5a892a1SMatthew G. Knepley pts[c++] = cp; 3917b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3918b5a892a1SMatthew G. Knepley } 3919b5a892a1SMatthew G. Knepley } 392009015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3921b5a892a1SMatthew G. Knepley } 3922b5a892a1SMatthew G. Knepley } 3923b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3924b5a892a1SMatthew G. Knepley *points = pts; 39253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3926b5a892a1SMatthew G. Knepley } 3927b5a892a1SMatthew G. Knepley 3928d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3929d71ae5a4SJacob Faibussowitsch { 3930b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3931b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3932b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3933b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3934b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3935b5a892a1SMatthew G. Knepley 3936b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3938b5a892a1SMatthew G. Knepley if (depth == 1) { 39399566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3941b5a892a1SMatthew G. Knepley } 39429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3943476787b7SMatthew 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; 3944*c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39459566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3947b5a892a1SMatthew G. Knepley } 39489566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3949b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3950b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3951b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39539371c9d4SSatish Balay if (*points) { 39549371c9d4SSatish Balay closure = *points; 39559371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3956b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3957b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3958b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3959b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3960b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3961b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3962b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3963b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3964b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3965b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 3966b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 396709015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 3968b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3969b5a892a1SMatthew G. Knepley 3970b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3971b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2; 397263a3b9bcSJacob 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); 3973b5a892a1SMatthew G. Knepley } 397409015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3975b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3976b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 3977b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 3978b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 39799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3980b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3981b5a892a1SMatthew G. Knepley PetscInt c; 3982b5a892a1SMatthew G. Knepley 3983b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3984b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3985b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3986b5a892a1SMatthew G. Knepley } 3987b5a892a1SMatthew G. Knepley if (c == closureSize) { 3988b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3989b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3990b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3991b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3992b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3993b5a892a1SMatthew G. Knepley } 3994b5a892a1SMatthew G. Knepley } 399509015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3996b5a892a1SMatthew G. Knepley } 39979566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 3998b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 3999b5a892a1SMatthew G. Knepley if (points) *points = closure; 40003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4001b5a892a1SMatthew G. Knepley } 4002b5a892a1SMatthew G. Knepley 4003552f7358SJed Brown /*@C 4004eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4005552f7358SJed Brown 4006a1cb98faSBarry Smith Not Collective 4007552f7358SJed Brown 4008552f7358SJed Brown Input Parameters: 4009a1cb98faSBarry Smith + dm - The `DMPLEX` 4010b5a892a1SMatthew G. Knepley . p - The mesh point 4011a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4012552f7358SJed Brown 40136b867d5aSJose E. Roman Input/Output Parameter: 40146b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 401520f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40166b867d5aSJose E. Roman 40176b867d5aSJose E. Roman Output Parameter: 401820f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4019552f7358SJed Brown 4020a1cb98faSBarry Smith Level: beginner 4021a1cb98faSBarry Smith 4022552f7358SJed Brown Note: 402320f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4024552f7358SJed Brown 402560225df5SJacob Faibussowitsch Fortran Notes: 402620f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40273813dfbdSMatthew G Knepley 40281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4029552f7358SJed Brown @*/ 4030d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4031d71ae5a4SJacob Faibussowitsch { 4032b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4033552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40344f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40354f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40389bf0dad6SMatthew G. Knepley } 40399bf0dad6SMatthew G. Knepley 4040552f7358SJed Brown /*@C 4041eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4042552f7358SJed Brown 4043a1cb98faSBarry Smith Not Collective 4044552f7358SJed Brown 4045552f7358SJed Brown Input Parameters: 4046a1cb98faSBarry Smith + dm - The `DMPLEX` 4047b5a892a1SMatthew G. Knepley . p - The mesh point 4048a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 404920f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4050b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4051552f7358SJed Brown 4052a1cb98faSBarry Smith Level: beginner 4053a1cb98faSBarry Smith 4054552f7358SJed Brown Note: 405520f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4056552f7358SJed Brown 40571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4058552f7358SJed Brown @*/ 4059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4060d71ae5a4SJacob Faibussowitsch { 4061b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4062552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40634ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40649566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4066552f7358SJed Brown } 4067552f7358SJed Brown 4068552f7358SJed Brown /*@ 4069eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4070552f7358SJed Brown 4071a1cb98faSBarry Smith Not Collective 4072552f7358SJed Brown 4073552f7358SJed Brown Input Parameter: 407460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4075552f7358SJed Brown 4076552f7358SJed Brown Output Parameters: 4077552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4078552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4079552f7358SJed Brown 4080552f7358SJed Brown Level: beginner 4081552f7358SJed Brown 40821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4083552f7358SJed Brown @*/ 4084d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4085d71ae5a4SJacob Faibussowitsch { 4086552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4087552f7358SJed Brown 4088552f7358SJed Brown PetscFunctionBegin; 4089552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40901baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 40911baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 40923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4093552f7358SJed Brown } 4094552f7358SJed Brown 4095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4096d71ae5a4SJacob Faibussowitsch { 4097552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 40986302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4099552f7358SJed Brown 4100552f7358SJed Brown PetscFunctionBegin; 4101552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41066302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41076302a7fbSVaclav Hapla if (maxSupportSize) { 41089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4111552f7358SJed Brown } 41123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4113552f7358SJed Brown } 4114552f7358SJed Brown 4115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4116d71ae5a4SJacob Faibussowitsch { 4117552f7358SJed Brown PetscFunctionBegin; 41189566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 41199566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 4120ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4121736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 412295602cf2SAlexis Marboeuf PetscSF sfNatural; 4123f94b4a02SBlaise Bourdin 41243dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 412695602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4127c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4128f94b4a02SBlaise Bourdin } 41293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4130552f7358SJed Brown } 4131552f7358SJed Brown 4132d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4133d71ae5a4SJacob Faibussowitsch { 41343dcd263cSBlaise Bourdin PetscInt i = 0; 41352adcc780SMatthew G. Knepley 41362adcc780SMatthew G. Knepley PetscFunctionBegin; 41379566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41389566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4139c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41403dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41413dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 414295602cf2SAlexis Marboeuf PetscSF sfNatural; 41433dcd263cSBlaise Bourdin 41443dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4146c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 414795602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4148c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41493dcd263cSBlaise Bourdin break; 41503dcd263cSBlaise Bourdin } 41513dcd263cSBlaise Bourdin } 41523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41532adcc780SMatthew G. Knepley } 41542adcc780SMatthew G. Knepley 4155552f7358SJed Brown /*@ 4156eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4157552f7358SJed Brown 4158a1cb98faSBarry Smith Not Collective 4159552f7358SJed Brown 4160552f7358SJed Brown Input Parameter: 416160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4162552f7358SJed Brown 4163552f7358SJed Brown Level: beginner 4164552f7358SJed Brown 4165a1cb98faSBarry Smith Note: 4166a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4167a1cb98faSBarry Smith 41681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4169552f7358SJed Brown @*/ 4170d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4171d71ae5a4SJacob Faibussowitsch { 4172552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4173552f7358SJed Brown PetscInt *offsets; 4174552f7358SJed Brown PetscInt supportSize; 4175552f7358SJed Brown PetscInt pStart, pEnd, p; 4176552f7358SJed Brown 4177552f7358SJed Brown PetscFunctionBegin; 4178552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 417928b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 41809566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4181552f7358SJed Brown /* Calculate support sizes */ 41829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4183552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4184552f7358SJed Brown PetscInt dof, off, c; 4185552f7358SJed Brown 41869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 41879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 418848a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4189552f7358SJed Brown } 41909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4191552f7358SJed Brown /* Calculate supports */ 41929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 41939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 41949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4195552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4196552f7358SJed Brown PetscInt dof, off, c; 4197552f7358SJed Brown 41989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 41999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4200552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4201552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4202552f7358SJed Brown PetscInt offS; 4203552f7358SJed Brown 42049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42050d644c17SKarl Rupp 4206552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4207552f7358SJed Brown ++offsets[q]; 4208552f7358SJed Brown } 4209552f7358SJed Brown } 42109566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4213552f7358SJed Brown } 4214552f7358SJed Brown 4215d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4216d71ae5a4SJacob Faibussowitsch { 4217277ea44aSLisandro Dalcin IS stratumIS; 4218277ea44aSLisandro Dalcin 4219277ea44aSLisandro Dalcin PetscFunctionBegin; 42203ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 422176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4222277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4223277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42249566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4225277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42269566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42279371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42289371c9d4SSatish Balay overlap = PETSC_TRUE; 42299371c9d4SSatish Balay break; 42309371c9d4SSatish Balay } 4231277ea44aSLisandro Dalcin } 423263a3b9bcSJacob 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); 4233277ea44aSLisandro Dalcin } 42349566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42359566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4238277ea44aSLisandro Dalcin } 4239277ea44aSLisandro Dalcin 4240552f7358SJed Brown /*@ 4241a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4242552f7358SJed Brown 424320f4b53cSBarry Smith Collective 4244552f7358SJed Brown 4245552f7358SJed Brown Input Parameter: 424660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4247552f7358SJed Brown 4248a1cb98faSBarry Smith Level: beginner 4249552f7358SJed Brown 4250552f7358SJed Brown Notes: 4251a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4252a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4253a4e35b19SJacob Faibussowitsch 4254a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4255a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4256a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4257b1bb481bSMatthew 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 4258a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4259a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4260a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4261552f7358SJed Brown 4262b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4263b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4264b1bb481bSMatthew 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 4265b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4266a1cb98faSBarry Smith .vb 4267a1cb98faSBarry Smith cone(c0) = {e0, v2} 4268a1cb98faSBarry Smith cone(e0) = {v0, v1} 4269a1cb98faSBarry Smith .ve 4270a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4271a1cb98faSBarry Smith .vb 4272a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4273a1cb98faSBarry Smith depth 1 = {e0, c0} 4274a1cb98faSBarry Smith .ve 4275b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4276b1bb481bSMatthew Knepley 4277a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4278552f7358SJed Brown 42791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4280552f7358SJed Brown @*/ 4281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4282d71ae5a4SJacob Faibussowitsch { 4283df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4284aa50250dSMatthew G. Knepley DMLabel label; 4285552f7358SJed Brown PetscInt pStart, pEnd, p; 4286552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 4287552f7358SJed Brown 4288552f7358SJed Brown PetscFunctionBegin; 4289552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4291277ea44aSLisandro Dalcin 4292277ea44aSLisandro Dalcin /* Create depth label */ 42939566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 42949566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 42959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4296277ea44aSLisandro Dalcin 4297277ea44aSLisandro Dalcin { 4298552f7358SJed Brown /* Initialize roots and count leaves */ 4299277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4300277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4301552f7358SJed Brown PetscInt coneSize, supportSize; 4302552f7358SJed Brown 4303277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 43049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 43059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4306552f7358SJed Brown if (!coneSize && supportSize) { 4307277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4308277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4309552f7358SJed Brown ++numRoots; 4310552f7358SJed Brown } else if (!supportSize && coneSize) { 4311552f7358SJed Brown ++numLeaves; 4312552f7358SJed Brown } else if (!supportSize && !coneSize) { 4313552f7358SJed Brown /* Isolated points */ 4314277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4315277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4316552f7358SJed Brown } 4317552f7358SJed Brown } 43189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4319277ea44aSLisandro Dalcin } 4320277ea44aSLisandro Dalcin 4321552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 4322277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4323277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 4324552f7358SJed Brown PetscInt coneSize, supportSize; 4325552f7358SJed Brown 4326277ea44aSLisandro Dalcin for (p = pStart; p < pEnd; ++p) { 43279566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 43289566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4329552f7358SJed Brown if (!supportSize && coneSize) { 4330277ea44aSLisandro Dalcin sMin = PetscMin(p, sMin); 4331277ea44aSLisandro Dalcin sMax = PetscMax(p, sMax); 4332552f7358SJed Brown } 4333552f7358SJed Brown } 43349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4335552f7358SJed Brown } else { 4336277ea44aSLisandro Dalcin PetscInt level = 0; 4337277ea44aSLisandro Dalcin PetscInt qStart, qEnd, q; 4338552f7358SJed Brown 43399566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4340277ea44aSLisandro Dalcin while (qEnd > qStart) { 4341277ea44aSLisandro Dalcin PetscInt sMin = PETSC_MAX_INT; 4342277ea44aSLisandro Dalcin PetscInt sMax = PETSC_MIN_INT; 434374ef644bSMatthew G. Knepley 4344277ea44aSLisandro Dalcin for (q = qStart; q < qEnd; ++q) { 434574ef644bSMatthew G. Knepley const PetscInt *support; 434674ef644bSMatthew G. Knepley PetscInt supportSize, s; 434774ef644bSMatthew G. Knepley 43489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 43499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, q, &support)); 435074ef644bSMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 4351277ea44aSLisandro Dalcin sMin = PetscMin(support[s], sMin); 4352277ea44aSLisandro Dalcin sMax = PetscMax(support[s], sMax); 4353552f7358SJed Brown } 4354552f7358SJed Brown } 43559566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &level)); 43569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 43579566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 435874ef644bSMatthew G. Knepley } 435974ef644bSMatthew G. Knepley } 4360bf4602e4SToby Isaac { /* just in case there is an empty process */ 4361bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4362bf4602e4SToby Isaac 43639566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4364712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 436548a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4366bf4602e4SToby Isaac } 43679566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 43689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 43693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4370552f7358SJed Brown } 4371552f7358SJed Brown 4372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4373d71ae5a4SJacob Faibussowitsch { 4374412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4375412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4376ba2698f1SMatthew G. Knepley 4377412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 43789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 43799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 43809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4381ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4382ba2698f1SMatthew G. Knepley if (depth <= 1) { 4383ba2698f1SMatthew G. Knepley switch (pdepth) { 4384d71ae5a4SJacob Faibussowitsch case 0: 4385d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4386d71ae5a4SJacob Faibussowitsch break; 4387ba2698f1SMatthew G. Knepley case 1: 4388ba2698f1SMatthew G. Knepley switch (coneSize) { 4389d71ae5a4SJacob Faibussowitsch case 2: 4390d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4391d71ae5a4SJacob Faibussowitsch break; 4392d71ae5a4SJacob Faibussowitsch case 3: 4393d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4394d71ae5a4SJacob Faibussowitsch break; 4395ba2698f1SMatthew G. Knepley case 4: 4396ba2698f1SMatthew G. Knepley switch (dim) { 4397d71ae5a4SJacob Faibussowitsch case 2: 4398d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4399d71ae5a4SJacob Faibussowitsch break; 4400d71ae5a4SJacob Faibussowitsch case 3: 4401d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4402d71ae5a4SJacob Faibussowitsch break; 4403d71ae5a4SJacob Faibussowitsch default: 4404d71ae5a4SJacob Faibussowitsch break; 4405ba2698f1SMatthew G. Knepley } 4406ba2698f1SMatthew G. Knepley break; 4407d71ae5a4SJacob Faibussowitsch case 5: 4408d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4409d71ae5a4SJacob Faibussowitsch break; 4410d71ae5a4SJacob Faibussowitsch case 6: 4411d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4412d71ae5a4SJacob Faibussowitsch break; 4413d71ae5a4SJacob Faibussowitsch case 8: 4414d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4415d71ae5a4SJacob Faibussowitsch break; 4416d71ae5a4SJacob Faibussowitsch default: 4417d71ae5a4SJacob Faibussowitsch break; 4418ba2698f1SMatthew G. Knepley } 4419ba2698f1SMatthew G. Knepley } 4420ba2698f1SMatthew G. Knepley } else { 4421ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4422ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4423ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4424ba2698f1SMatthew G. Knepley switch (dim) { 4425ba2698f1SMatthew G. Knepley case 1: 4426ba2698f1SMatthew G. Knepley switch (coneSize) { 4427d71ae5a4SJacob Faibussowitsch case 2: 4428d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4429d71ae5a4SJacob Faibussowitsch break; 4430d71ae5a4SJacob Faibussowitsch default: 4431d71ae5a4SJacob Faibussowitsch break; 4432ba2698f1SMatthew G. Knepley } 4433ba2698f1SMatthew G. Knepley break; 4434ba2698f1SMatthew G. Knepley case 2: 4435ba2698f1SMatthew G. Knepley switch (coneSize) { 4436d71ae5a4SJacob Faibussowitsch case 3: 4437d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4438d71ae5a4SJacob Faibussowitsch break; 4439d71ae5a4SJacob Faibussowitsch case 4: 4440d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4441d71ae5a4SJacob Faibussowitsch break; 4442d71ae5a4SJacob Faibussowitsch default: 4443d71ae5a4SJacob Faibussowitsch break; 4444ba2698f1SMatthew G. Knepley } 4445ba2698f1SMatthew G. Knepley break; 4446ba2698f1SMatthew G. Knepley case 3: 4447ba2698f1SMatthew G. Knepley switch (coneSize) { 4448d71ae5a4SJacob Faibussowitsch case 4: 4449d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4450d71ae5a4SJacob Faibussowitsch break; 44519371c9d4SSatish Balay case 5: { 4452da9060c4SMatthew G. Knepley const PetscInt *cone; 4453da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4454da9060c4SMatthew G. Knepley 44559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 44569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4457da9060c4SMatthew G. Knepley switch (faceConeSize) { 4458d71ae5a4SJacob Faibussowitsch case 3: 4459d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4460d71ae5a4SJacob Faibussowitsch break; 4461d71ae5a4SJacob Faibussowitsch case 4: 4462d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4463d71ae5a4SJacob Faibussowitsch break; 4464da9060c4SMatthew G. Knepley } 44659371c9d4SSatish Balay } break; 4466d71ae5a4SJacob Faibussowitsch case 6: 4467d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4468d71ae5a4SJacob Faibussowitsch break; 4469d71ae5a4SJacob Faibussowitsch default: 4470d71ae5a4SJacob Faibussowitsch break; 4471ba2698f1SMatthew G. Knepley } 4472ba2698f1SMatthew G. Knepley break; 4473d71ae5a4SJacob Faibussowitsch default: 4474d71ae5a4SJacob Faibussowitsch break; 4475ba2698f1SMatthew G. Knepley } 4476ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4477ba2698f1SMatthew G. Knepley switch (coneSize) { 4478d71ae5a4SJacob Faibussowitsch case 2: 4479d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4480d71ae5a4SJacob Faibussowitsch break; 4481d71ae5a4SJacob Faibussowitsch case 3: 4482d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4483d71ae5a4SJacob Faibussowitsch break; 4484d71ae5a4SJacob Faibussowitsch case 4: 4485d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4486d71ae5a4SJacob Faibussowitsch break; 4487d71ae5a4SJacob Faibussowitsch default: 4488d71ae5a4SJacob Faibussowitsch break; 4489ba2698f1SMatthew G. Knepley } 4490ba2698f1SMatthew G. Knepley } 4491ba2698f1SMatthew G. Knepley } 4492412e9a14SMatthew G. Knepley *pt = ct; 44933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4494ba2698f1SMatthew G. Knepley } 4495412e9a14SMatthew G. Knepley 4496412e9a14SMatthew G. Knepley /*@ 4497412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4498412e9a14SMatthew G. Knepley 449920f4b53cSBarry Smith Collective 4500412e9a14SMatthew G. Knepley 4501412e9a14SMatthew G. Knepley Input Parameter: 450260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4503412e9a14SMatthew G. Knepley 4504412e9a14SMatthew G. Knepley Level: developer 4505412e9a14SMatthew G. Knepley 4506a1cb98faSBarry Smith Note: 4507a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4508a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4509a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4510412e9a14SMatthew G. Knepley 4511a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4512a1cb98faSBarry Smith 45131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4514412e9a14SMatthew G. Knepley @*/ 4515d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4516d71ae5a4SJacob Faibussowitsch { 4517412e9a14SMatthew G. Knepley DM_Plex *mesh; 4518412e9a14SMatthew G. Knepley DMLabel ctLabel; 4519412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4520412e9a14SMatthew G. Knepley 4521412e9a14SMatthew G. Knepley PetscFunctionBegin; 4522412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4523412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 45249566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 45259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 45269566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 452721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 452821027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4529412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4530327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4531412e9a14SMatthew G. Knepley PetscInt pdepth; 4532412e9a14SMatthew G. Knepley 45339566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 45349566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4535476787b7SMatthew 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); 45369566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 453721027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4538412e9a14SMatthew G. Knepley } 45399566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 45409566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 45413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4542ba2698f1SMatthew G. Knepley } 4543ba2698f1SMatthew G. Knepley 4544552f7358SJed Brown /*@C 4545552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4546552f7358SJed Brown 4547552f7358SJed Brown Not Collective 4548552f7358SJed Brown 4549552f7358SJed Brown Input Parameters: 4550a1cb98faSBarry Smith + dm - The `DMPLEX` object 4551552f7358SJed Brown . numPoints - The number of input points for the join 4552552f7358SJed Brown - points - The input points 4553552f7358SJed Brown 4554552f7358SJed Brown Output Parameters: 4555552f7358SJed Brown + numCoveredPoints - The number of points in the join 4556552f7358SJed Brown - coveredPoints - The points in the join 4557552f7358SJed Brown 4558552f7358SJed Brown Level: intermediate 4559552f7358SJed Brown 4560a1cb98faSBarry Smith Note: 4561a1cb98faSBarry Smith Currently, this is restricted to a single level join 4562552f7358SJed Brown 456360225df5SJacob Faibussowitsch Fortran Notes: 456420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 45653813dfbdSMatthew G Knepley 45661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4567552f7358SJed Brown @*/ 4568d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4569d71ae5a4SJacob Faibussowitsch { 4570552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4571552f7358SJed Brown PetscInt *join[2]; 4572552f7358SJed Brown PetscInt joinSize, i = 0; 4573552f7358SJed Brown PetscInt dof, off, p, c, m; 45746302a7fbSVaclav Hapla PetscInt maxSupportSize; 4575552f7358SJed Brown 4576552f7358SJed Brown PetscFunctionBegin; 4577552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 45784f572ea9SToby Isaac PetscAssertPointer(points, 3); 45794f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 45804f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 45816302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 45826302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 45836302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4584552f7358SJed Brown /* Copy in support of first point */ 45859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 45869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4587ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4588552f7358SJed Brown /* Check each successive support */ 4589552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4590552f7358SJed Brown PetscInt newJoinSize = 0; 4591552f7358SJed Brown 45929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 45939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4594552f7358SJed Brown for (c = 0; c < dof; ++c) { 4595552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4596552f7358SJed Brown 4597552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4598552f7358SJed Brown if (point == join[i][m]) { 4599552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4600552f7358SJed Brown break; 4601552f7358SJed Brown } 4602552f7358SJed Brown } 4603552f7358SJed Brown } 4604552f7358SJed Brown joinSize = newJoinSize; 4605552f7358SJed Brown i = 1 - i; 4606552f7358SJed Brown } 4607552f7358SJed Brown *numCoveredPoints = joinSize; 4608552f7358SJed Brown *coveredPoints = join[i]; 46096302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 46103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4611552f7358SJed Brown } 4612552f7358SJed Brown 4613552f7358SJed Brown /*@C 4614552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4615552f7358SJed Brown 4616552f7358SJed Brown Not Collective 4617552f7358SJed Brown 4618552f7358SJed Brown Input Parameters: 4619a1cb98faSBarry Smith + dm - The `DMPLEX` object 4620552f7358SJed Brown . numPoints - The number of input points for the join 4621552f7358SJed Brown - points - The input points 4622552f7358SJed Brown 4623552f7358SJed Brown Output Parameters: 4624552f7358SJed Brown + numCoveredPoints - The number of points in the join 4625552f7358SJed Brown - coveredPoints - The points in the join 4626552f7358SJed Brown 4627552f7358SJed Brown Level: intermediate 4628552f7358SJed Brown 462960225df5SJacob Faibussowitsch Fortran Notes: 463020f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4631a1cb98faSBarry Smith 46321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4633552f7358SJed Brown @*/ 4634d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4635d71ae5a4SJacob Faibussowitsch { 4636552f7358SJed Brown PetscFunctionBegin; 4637552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46384f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 46394f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 46404f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46419566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4642d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 46433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4644552f7358SJed Brown } 4645552f7358SJed Brown 4646552f7358SJed Brown /*@C 4647552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4648552f7358SJed Brown 4649552f7358SJed Brown Not Collective 4650552f7358SJed Brown 4651552f7358SJed Brown Input Parameters: 4652a1cb98faSBarry Smith + dm - The `DMPLEX` object 4653552f7358SJed Brown . numPoints - The number of input points for the join 4654552f7358SJed Brown - points - The input points 4655552f7358SJed Brown 4656552f7358SJed Brown Output Parameters: 4657552f7358SJed Brown + numCoveredPoints - The number of points in the join 4658552f7358SJed Brown - coveredPoints - The points in the join 4659552f7358SJed Brown 4660552f7358SJed Brown Level: intermediate 4661552f7358SJed Brown 466260225df5SJacob Faibussowitsch Fortran Notes: 466320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4664a1cb98faSBarry Smith 46651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4666552f7358SJed Brown @*/ 4667d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4668d71ae5a4SJacob Faibussowitsch { 4669552f7358SJed Brown PetscInt *offsets, **closures; 4670552f7358SJed Brown PetscInt *join[2]; 4671552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 467224c766afSToby Isaac PetscInt p, d, c, m, ms; 4673552f7358SJed Brown 4674552f7358SJed Brown PetscFunctionBegin; 4675552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46764f572ea9SToby Isaac PetscAssertPointer(points, 3); 46774f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46784f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4679552f7358SJed Brown 46809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 46819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 46829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 46836302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 468424c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 46859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 46869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4687552f7358SJed Brown 4688552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4689552f7358SJed Brown PetscInt closureSize; 4690552f7358SJed Brown 46919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 46920d644c17SKarl Rupp 4693552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4694552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4695552f7358SJed Brown PetscInt pStart, pEnd, i; 4696552f7358SJed Brown 46979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4698552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4699552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4700552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4701552f7358SJed Brown break; 4702552f7358SJed Brown } 4703552f7358SJed Brown } 4704552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4705552f7358SJed Brown } 470663a3b9bcSJacob 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); 4707552f7358SJed Brown } 4708552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4709552f7358SJed Brown PetscInt dof; 4710552f7358SJed Brown 4711552f7358SJed Brown /* Copy in support of first point */ 4712552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4713ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4714552f7358SJed Brown /* Check each successive cone */ 4715552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4716552f7358SJed Brown PetscInt newJoinSize = 0; 4717552f7358SJed Brown 4718552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4719552f7358SJed Brown for (c = 0; c < dof; ++c) { 4720552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4721552f7358SJed Brown 4722552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4723552f7358SJed Brown if (point == join[i][m]) { 4724552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4725552f7358SJed Brown break; 4726552f7358SJed Brown } 4727552f7358SJed Brown } 4728552f7358SJed Brown } 4729552f7358SJed Brown joinSize = newJoinSize; 4730552f7358SJed Brown i = 1 - i; 4731552f7358SJed Brown } 4732552f7358SJed Brown if (joinSize) break; 4733552f7358SJed Brown } 4734552f7358SJed Brown *numCoveredPoints = joinSize; 4735552f7358SJed Brown *coveredPoints = join[i]; 473648a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 47379566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 47389566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47396302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 47403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4741552f7358SJed Brown } 4742552f7358SJed Brown 4743552f7358SJed Brown /*@C 4744552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4745552f7358SJed Brown 4746552f7358SJed Brown Not Collective 4747552f7358SJed Brown 4748552f7358SJed Brown Input Parameters: 4749a1cb98faSBarry Smith + dm - The `DMPLEX` object 4750552f7358SJed Brown . numPoints - The number of input points for the meet 4751552f7358SJed Brown - points - The input points 4752552f7358SJed Brown 4753552f7358SJed Brown Output Parameters: 475460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 475560225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4756552f7358SJed Brown 4757552f7358SJed Brown Level: intermediate 4758552f7358SJed Brown 4759a1cb98faSBarry Smith Note: 4760a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4761552f7358SJed Brown 47623813dfbdSMatthew G Knepley Fortran Notes: 476320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 47643813dfbdSMatthew G Knepley 47651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4766552f7358SJed Brown @*/ 4767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4768d71ae5a4SJacob Faibussowitsch { 4769552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4770552f7358SJed Brown PetscInt *meet[2]; 4771552f7358SJed Brown PetscInt meetSize, i = 0; 4772552f7358SJed Brown PetscInt dof, off, p, c, m; 47736302a7fbSVaclav Hapla PetscInt maxConeSize; 4774552f7358SJed Brown 4775552f7358SJed Brown PetscFunctionBegin; 4776552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47774f572ea9SToby Isaac PetscAssertPointer(points, 3); 47784f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 47794f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 47806302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 47816302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 47826302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4783552f7358SJed Brown /* Copy in cone of first point */ 47849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 47859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4786ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4787552f7358SJed Brown /* Check each successive cone */ 4788552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4789552f7358SJed Brown PetscInt newMeetSize = 0; 4790552f7358SJed Brown 47919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 47929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4793552f7358SJed Brown for (c = 0; c < dof; ++c) { 4794552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4795552f7358SJed Brown 4796552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4797552f7358SJed Brown if (point == meet[i][m]) { 4798552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4799552f7358SJed Brown break; 4800552f7358SJed Brown } 4801552f7358SJed Brown } 4802552f7358SJed Brown } 4803552f7358SJed Brown meetSize = newMeetSize; 4804552f7358SJed Brown i = 1 - i; 4805552f7358SJed Brown } 4806552f7358SJed Brown *numCoveringPoints = meetSize; 4807552f7358SJed Brown *coveringPoints = meet[i]; 48086302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4810552f7358SJed Brown } 4811552f7358SJed Brown 4812552f7358SJed Brown /*@C 4813552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4814552f7358SJed Brown 4815552f7358SJed Brown Not Collective 4816552f7358SJed Brown 4817552f7358SJed Brown Input Parameters: 4818a1cb98faSBarry Smith + dm - The `DMPLEX` object 4819552f7358SJed Brown . numPoints - The number of input points for the meet 4820552f7358SJed Brown - points - The input points 4821552f7358SJed Brown 4822552f7358SJed Brown Output Parameters: 4823552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4824552f7358SJed Brown - coveredPoints - The points in the meet 4825552f7358SJed Brown 4826552f7358SJed Brown Level: intermediate 4827552f7358SJed Brown 482860225df5SJacob Faibussowitsch Fortran Notes: 482920f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48303813dfbdSMatthew G Knepley 48311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4832552f7358SJed Brown @*/ 4833d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4834d71ae5a4SJacob Faibussowitsch { 4835552f7358SJed Brown PetscFunctionBegin; 4836552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48374f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 48384f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 48394f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 48409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4841d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 48423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4843552f7358SJed Brown } 4844552f7358SJed Brown 4845552f7358SJed Brown /*@C 4846552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4847552f7358SJed Brown 4848552f7358SJed Brown Not Collective 4849552f7358SJed Brown 4850552f7358SJed Brown Input Parameters: 4851a1cb98faSBarry Smith + dm - The `DMPLEX` object 4852552f7358SJed Brown . numPoints - The number of input points for the meet 4853552f7358SJed Brown - points - The input points 4854552f7358SJed Brown 4855552f7358SJed Brown Output Parameters: 4856552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4857552f7358SJed Brown - coveredPoints - The points in the meet 4858552f7358SJed Brown 4859552f7358SJed Brown Level: intermediate 4860552f7358SJed Brown 486160225df5SJacob Faibussowitsch Fortran Notes: 486220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48633813dfbdSMatthew G Knepley 48641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4865552f7358SJed Brown @*/ 4866d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4867d71ae5a4SJacob Faibussowitsch { 4868552f7358SJed Brown PetscInt *offsets, **closures; 4869552f7358SJed Brown PetscInt *meet[2]; 4870552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 487124c766afSToby Isaac PetscInt p, h, c, m, mc; 4872552f7358SJed Brown 4873552f7358SJed Brown PetscFunctionBegin; 4874552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48754f572ea9SToby Isaac PetscAssertPointer(points, 3); 48764f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 48774f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4878552f7358SJed Brown 48799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 48809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 48819566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 48826302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 488324c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 48849566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 48859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4886552f7358SJed Brown 4887552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4888552f7358SJed Brown PetscInt closureSize; 4889552f7358SJed Brown 48909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 48910d644c17SKarl Rupp 4892552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4893552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4894552f7358SJed Brown PetscInt pStart, pEnd, i; 4895552f7358SJed Brown 48969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4897552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4898552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4899552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4900552f7358SJed Brown break; 4901552f7358SJed Brown } 4902552f7358SJed Brown } 4903552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4904552f7358SJed Brown } 490563a3b9bcSJacob 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); 4906552f7358SJed Brown } 4907552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4908552f7358SJed Brown PetscInt dof; 4909552f7358SJed Brown 4910552f7358SJed Brown /* Copy in cone of first point */ 4911552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4912ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4913552f7358SJed Brown /* Check each successive cone */ 4914552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4915552f7358SJed Brown PetscInt newMeetSize = 0; 4916552f7358SJed Brown 4917552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 4918552f7358SJed Brown for (c = 0; c < dof; ++c) { 4919552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 4920552f7358SJed Brown 4921552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4922552f7358SJed Brown if (point == meet[i][m]) { 4923552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4924552f7358SJed Brown break; 4925552f7358SJed Brown } 4926552f7358SJed Brown } 4927552f7358SJed Brown } 4928552f7358SJed Brown meetSize = newMeetSize; 4929552f7358SJed Brown i = 1 - i; 4930552f7358SJed Brown } 4931552f7358SJed Brown if (meetSize) break; 4932552f7358SJed Brown } 4933552f7358SJed Brown *numCoveredPoints = meetSize; 4934552f7358SJed Brown *coveredPoints = meet[i]; 493548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 49369566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 49379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49386302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 49393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4940552f7358SJed Brown } 4941552f7358SJed Brown 49424e3744c5SMatthew G. Knepley /*@C 4943a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 49444e3744c5SMatthew G. Knepley 49454e3744c5SMatthew G. Knepley Not Collective 49464e3744c5SMatthew G. Knepley 49474e3744c5SMatthew G. Knepley Input Parameters: 4948a1cb98faSBarry Smith + dmA - A `DMPLEX` object 4949a1cb98faSBarry Smith - dmB - A `DMPLEX` object 49504e3744c5SMatthew G. Knepley 49512fe279fdSBarry Smith Output Parameter: 4952a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 49534e3744c5SMatthew G. Knepley 49544e3744c5SMatthew G. Knepley Level: intermediate 49554e3744c5SMatthew G. Knepley 4956a1cb98faSBarry Smith Note: 49573c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 49584e3744c5SMatthew G. Knepley 49591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 49604e3744c5SMatthew G. Knepley @*/ 4961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 4962d71ae5a4SJacob Faibussowitsch { 49634e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 49644e3744c5SMatthew G. Knepley 49654e3744c5SMatthew G. Knepley PetscFunctionBegin; 49664e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 49674e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 49684f572ea9SToby Isaac PetscAssertPointer(equal, 3); 49694e3744c5SMatthew G. Knepley 49704e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 49719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 49729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 49733ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 49749566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 49759566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 49763ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 49774e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 49784e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 49794e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 49804e3744c5SMatthew G. Knepley 49819566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 49829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 49839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 49849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 49859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 49869566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 49873ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 49884e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 49893ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 49903ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 49914e3744c5SMatthew G. Knepley } 49929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 49939566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 49949566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 49959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 49963ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 49974e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 49983ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 49994e3744c5SMatthew G. Knepley } 50004e3744c5SMatthew G. Knepley } 50014e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50034e3744c5SMatthew G. Knepley } 50044e3744c5SMatthew G. Knepley 50057cd05799SMatthew G. Knepley /*@C 50067cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50077cd05799SMatthew G. Knepley 50087cd05799SMatthew G. Knepley Not Collective 50097cd05799SMatthew G. Knepley 50107cd05799SMatthew G. Knepley Input Parameters: 5011a1cb98faSBarry Smith + dm - The `DMPLEX` 50127cd05799SMatthew G. Knepley . cellDim - The cell dimension 50137cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 50147cd05799SMatthew G. Knepley 50152fe279fdSBarry Smith Output Parameter: 50167cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 50177cd05799SMatthew G. Knepley 50187cd05799SMatthew G. Knepley Level: developer 50197cd05799SMatthew G. Knepley 5020a1cb98faSBarry Smith Note: 50217cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 50227cd05799SMatthew G. Knepley 50231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50247cd05799SMatthew G. Knepley @*/ 5025d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5026d71ae5a4SJacob Faibussowitsch { 502782f516ccSBarry Smith MPI_Comm comm; 5028552f7358SJed Brown 5029552f7358SJed Brown PetscFunctionBegin; 50309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 50314f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5032552f7358SJed Brown switch (cellDim) { 5033d71ae5a4SJacob Faibussowitsch case 0: 5034d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5035d71ae5a4SJacob Faibussowitsch break; 5036d71ae5a4SJacob Faibussowitsch case 1: 5037d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5038d71ae5a4SJacob Faibussowitsch break; 5039552f7358SJed Brown case 2: 5040552f7358SJed Brown switch (numCorners) { 504119436ca2SJed Brown case 3: /* triangle */ 504219436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5043552f7358SJed Brown break; 504419436ca2SJed Brown case 4: /* quadrilateral */ 504519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5046552f7358SJed Brown break; 504719436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 504819436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5049552f7358SJed Brown break; 505019436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 505119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5052552f7358SJed Brown break; 5053d71ae5a4SJacob Faibussowitsch default: 5054d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5055552f7358SJed Brown } 5056552f7358SJed Brown break; 5057552f7358SJed Brown case 3: 5058552f7358SJed Brown switch (numCorners) { 505919436ca2SJed Brown case 4: /* tetradehdron */ 506019436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5061552f7358SJed Brown break; 506219436ca2SJed Brown case 6: /* tet cohesive cells */ 506319436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5064552f7358SJed Brown break; 506519436ca2SJed Brown case 8: /* hexahedron */ 506619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5067552f7358SJed Brown break; 506819436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 506919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5070552f7358SJed Brown break; 507119436ca2SJed Brown case 10: /* quadratic tetrahedron */ 507219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5073552f7358SJed Brown break; 507419436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 507519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5076552f7358SJed Brown break; 507719436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 507819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5079552f7358SJed Brown break; 508019436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 508119436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5082552f7358SJed Brown break; 5083d71ae5a4SJacob Faibussowitsch default: 5084d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5085552f7358SJed Brown } 5086552f7358SJed Brown break; 5087d71ae5a4SJacob Faibussowitsch default: 5088d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5089552f7358SJed Brown } 50903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5091552f7358SJed Brown } 5092552f7358SJed Brown 5093552f7358SJed Brown /*@ 5094a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5095552f7358SJed Brown 5096552f7358SJed Brown Not Collective 5097552f7358SJed Brown 5098aa50250dSMatthew G. Knepley Input Parameter: 5099a1cb98faSBarry Smith . dm - The `DMPLEX` object 5100552f7358SJed Brown 5101aa50250dSMatthew G. Knepley Output Parameter: 5102a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5103552f7358SJed Brown 5104552f7358SJed Brown Level: developer 5105552f7358SJed Brown 51061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5107aa50250dSMatthew G. Knepley @*/ 5108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5109d71ae5a4SJacob Faibussowitsch { 5110aa50250dSMatthew G. Knepley PetscFunctionBegin; 5111aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51124f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5113c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 51143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5115aa50250dSMatthew G. Knepley } 5116aa50250dSMatthew G. Knepley 5117aa50250dSMatthew G. Knepley /*@ 5118aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5119aa50250dSMatthew G. Knepley 5120aa50250dSMatthew G. Knepley Not Collective 5121aa50250dSMatthew G. Knepley 5122aa50250dSMatthew G. Knepley Input Parameter: 5123a1cb98faSBarry Smith . dm - The `DMPLEX` object 5124aa50250dSMatthew G. Knepley 5125aa50250dSMatthew G. Knepley Output Parameter: 5126aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5127aa50250dSMatthew G. Knepley 5128aa50250dSMatthew G. Knepley Level: developer 5129552f7358SJed Brown 5130b1bb481bSMatthew Knepley Notes: 5131a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5132a1cb98faSBarry Smith 5133a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5134a1cb98faSBarry Smith 5135dc287ab2SVaclav Hapla An empty mesh gives -1. 5136b1bb481bSMatthew Knepley 51371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5138552f7358SJed Brown @*/ 5139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5140d71ae5a4SJacob Faibussowitsch { 51419f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5142aa50250dSMatthew G. Knepley DMLabel label; 5143aa50250dSMatthew G. Knepley PetscInt d = 0; 5144552f7358SJed Brown 5145552f7358SJed Brown PetscFunctionBegin; 5146552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51474f572ea9SToby Isaac PetscAssertPointer(depth, 2); 51489f4ada15SMatthew G. Knepley if (mesh->tr) { 51499f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 51509f4ada15SMatthew G. Knepley } else { 51519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 51529566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5153552f7358SJed Brown *depth = d - 1; 51549f4ada15SMatthew G. Knepley } 51553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5156552f7358SJed Brown } 5157552f7358SJed Brown 5158552f7358SJed Brown /*@ 515920f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5160552f7358SJed Brown 5161552f7358SJed Brown Not Collective 5162552f7358SJed Brown 5163552f7358SJed Brown Input Parameters: 5164a1cb98faSBarry Smith + dm - The `DMPLEX` object 5165570fa34dSVaclav Hapla - depth - The requested depth 5166552f7358SJed Brown 5167552f7358SJed Brown Output Parameters: 516820f4b53cSBarry Smith + start - The first point at this `depth` 516920f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5170552f7358SJed Brown 5171552f7358SJed Brown Level: developer 5172552f7358SJed Brown 5173a1cb98faSBarry Smith Notes: 5174a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5175a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5176a1cb98faSBarry Smith higher dimension, e.g., "edges". 5177a1cb98faSBarry Smith 51782827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5179552f7358SJed Brown @*/ 5180d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5181d71ae5a4SJacob Faibussowitsch { 51829f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5183aa50250dSMatthew G. Knepley DMLabel label; 518463d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5185552f7358SJed Brown 5186552f7358SJed Brown PetscFunctionBegin; 5187552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51889371c9d4SSatish Balay if (start) { 51894f572ea9SToby Isaac PetscAssertPointer(start, 3); 51909371c9d4SSatish Balay *start = 0; 51919371c9d4SSatish Balay } 51929371c9d4SSatish Balay if (end) { 51934f572ea9SToby Isaac PetscAssertPointer(end, 4); 51949371c9d4SSatish Balay *end = 0; 51959371c9d4SSatish Balay } 51969566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 51973ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5198570fa34dSVaclav Hapla if (depth < 0) { 519963d1a920SMatthew G. Knepley if (start) *start = pStart; 520063d1a920SMatthew G. Knepley if (end) *end = pEnd; 52013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5202552f7358SJed Brown } 52039f4ada15SMatthew G. Knepley if (mesh->tr) { 52049f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52059f4ada15SMatthew G. Knepley } else { 52069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 520728b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5208570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52099f4ada15SMatthew G. Knepley } 52103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5211552f7358SJed Brown } 5212552f7358SJed Brown 5213552f7358SJed Brown /*@ 521420f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5215552f7358SJed Brown 5216552f7358SJed Brown Not Collective 5217552f7358SJed Brown 5218552f7358SJed Brown Input Parameters: 5219a1cb98faSBarry Smith + dm - The `DMPLEX` object 5220570fa34dSVaclav Hapla - height - The requested height 5221552f7358SJed Brown 5222552f7358SJed Brown Output Parameters: 522320f4b53cSBarry Smith + start - The first point at this `height` 522420f4b53cSBarry Smith - end - One beyond the last point at this `height` 5225552f7358SJed Brown 5226552f7358SJed Brown Level: developer 5227552f7358SJed Brown 5228a1cb98faSBarry Smith Notes: 5229a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5230a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5231a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5232a1cb98faSBarry Smith 52332827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5234552f7358SJed Brown @*/ 5235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5236d71ae5a4SJacob Faibussowitsch { 5237aa50250dSMatthew G. Knepley DMLabel label; 523863d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5239552f7358SJed Brown 5240552f7358SJed Brown PetscFunctionBegin; 5241552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52429371c9d4SSatish Balay if (start) { 52434f572ea9SToby Isaac PetscAssertPointer(start, 3); 52449371c9d4SSatish Balay *start = 0; 52459371c9d4SSatish Balay } 52469371c9d4SSatish Balay if (end) { 52474f572ea9SToby Isaac PetscAssertPointer(end, 4); 52489371c9d4SSatish Balay *end = 0; 52499371c9d4SSatish Balay } 52509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52513ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5252570fa34dSVaclav Hapla if (height < 0) { 525363d1a920SMatthew G. Knepley if (start) *start = pStart; 525463d1a920SMatthew G. Knepley if (end) *end = pEnd; 52553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5256552f7358SJed Brown } 52579566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 525859e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 525959e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 526059e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 526159e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 52623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5263552f7358SJed Brown } 5264552f7358SJed Brown 5265ba2698f1SMatthew G. Knepley /*@ 526620f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5267ba2698f1SMatthew G. Knepley 5268ba2698f1SMatthew G. Knepley Not Collective 5269ba2698f1SMatthew G. Knepley 5270d8d19677SJose E. Roman Input Parameters: 5271a1cb98faSBarry Smith + dm - The `DMPLEX` object 5272ba2698f1SMatthew G. Knepley - point - The point 5273ba2698f1SMatthew G. Knepley 5274ba2698f1SMatthew G. Knepley Output Parameter: 527520f4b53cSBarry Smith . depth - The depth of the `point` 5276ba2698f1SMatthew G. Knepley 5277ba2698f1SMatthew G. Knepley Level: intermediate 5278ba2698f1SMatthew G. Knepley 52791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5280ba2698f1SMatthew G. Knepley @*/ 5281d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5282d71ae5a4SJacob Faibussowitsch { 5283ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5284ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52854f572ea9SToby Isaac PetscAssertPointer(depth, 3); 52869566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 52873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5288ba2698f1SMatthew G. Knepley } 5289ba2698f1SMatthew G. Knepley 5290ba2698f1SMatthew G. Knepley /*@ 529120f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 52920c0a32dcSVaclav Hapla 52930c0a32dcSVaclav Hapla Not Collective 52940c0a32dcSVaclav Hapla 5295d8d19677SJose E. Roman Input Parameters: 5296a1cb98faSBarry Smith + dm - The `DMPLEX` object 52970c0a32dcSVaclav Hapla - point - The point 52980c0a32dcSVaclav Hapla 52990c0a32dcSVaclav Hapla Output Parameter: 530020f4b53cSBarry Smith . height - The height of the `point` 53010c0a32dcSVaclav Hapla 53020c0a32dcSVaclav Hapla Level: intermediate 53030c0a32dcSVaclav Hapla 53041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53050c0a32dcSVaclav Hapla @*/ 5306d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5307d71ae5a4SJacob Faibussowitsch { 53080c0a32dcSVaclav Hapla PetscInt n, pDepth; 53090c0a32dcSVaclav Hapla 53100c0a32dcSVaclav Hapla PetscFunctionBegin; 53110c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53124f572ea9SToby Isaac PetscAssertPointer(height, 3); 53139566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 53149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 53150c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 53163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53170c0a32dcSVaclav Hapla } 53180c0a32dcSVaclav Hapla 53190c0a32dcSVaclav Hapla /*@ 5320a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5321ba2698f1SMatthew G. Knepley 5322ba2698f1SMatthew G. Knepley Not Collective 5323ba2698f1SMatthew G. Knepley 5324ba2698f1SMatthew G. Knepley Input Parameter: 5325a1cb98faSBarry Smith . dm - The `DMPLEX` object 5326ba2698f1SMatthew G. Knepley 5327ba2698f1SMatthew G. Knepley Output Parameter: 5328a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5329412e9a14SMatthew G. Knepley 5330ba2698f1SMatthew G. Knepley Level: developer 5331ba2698f1SMatthew G. Knepley 5332a1cb98faSBarry Smith Note: 5333a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5334a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5335a1cb98faSBarry Smith 53361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5337ba2698f1SMatthew G. Knepley @*/ 5338d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5339d71ae5a4SJacob Faibussowitsch { 5340ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5341ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53424f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 53439566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5344ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 53453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5346ba2698f1SMatthew G. Knepley } 5347ba2698f1SMatthew G. Knepley 5348ba2698f1SMatthew G. Knepley /*@ 5349ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5350ba2698f1SMatthew G. Knepley 5351ba2698f1SMatthew G. Knepley Not Collective 5352ba2698f1SMatthew G. Knepley 5353d8d19677SJose E. Roman Input Parameters: 5354a1cb98faSBarry Smith + dm - The `DMPLEX` object 5355ba2698f1SMatthew G. Knepley - cell - The cell 5356ba2698f1SMatthew G. Knepley 5357ba2698f1SMatthew G. Knepley Output Parameter: 5358ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5359ba2698f1SMatthew G. Knepley 5360ba2698f1SMatthew G. Knepley Level: intermediate 5361ba2698f1SMatthew G. Knepley 53621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5363ba2698f1SMatthew G. Knepley @*/ 5364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5365d71ae5a4SJacob Faibussowitsch { 53669f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5367ba2698f1SMatthew G. Knepley DMLabel label; 5368ba2698f1SMatthew G. Knepley PetscInt ct; 5369ba2698f1SMatthew G. Knepley 5370ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5371ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53724f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 53739f4ada15SMatthew G. Knepley if (mesh->tr) { 53749f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 53759f4ada15SMatthew G. Knepley } else { 537621027e53SStefano Zampini PetscInt pStart, pEnd; 537721027e53SStefano Zampini 537821027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 537921027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 538021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 538121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 538221027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 538321027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 538421027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 538521027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 538621027e53SStefano Zampini } 538721027e53SStefano Zampini } 538821027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 538921027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 53909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 53919566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 539263a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5393936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 539421027e53SStefano Zampini } 53959f4ada15SMatthew G. Knepley } 53963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5397ba2698f1SMatthew G. Knepley } 5398ba2698f1SMatthew G. Knepley 5399412e9a14SMatthew G. Knepley /*@ 5400412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5401412e9a14SMatthew G. Knepley 5402412e9a14SMatthew G. Knepley Not Collective 5403412e9a14SMatthew G. Knepley 5404412e9a14SMatthew G. Knepley Input Parameters: 5405a1cb98faSBarry Smith + dm - The `DMPLEX` object 5406412e9a14SMatthew G. Knepley . cell - The cell 5407412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5408412e9a14SMatthew G. Knepley 5409a1cb98faSBarry Smith Level: advanced 5410a1cb98faSBarry Smith 5411a1cb98faSBarry Smith Note: 5412a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5413412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5414412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5415db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5416412e9a14SMatthew G. Knepley 54171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5418412e9a14SMatthew G. Knepley @*/ 5419d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5420d71ae5a4SJacob Faibussowitsch { 542121027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5422412e9a14SMatthew G. Knepley DMLabel label; 542321027e53SStefano Zampini PetscInt pStart, pEnd; 5424412e9a14SMatthew G. Knepley 5425412e9a14SMatthew G. Knepley PetscFunctionBegin; 5426412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 542721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 54289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54299566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 543021027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 543121027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 54323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5433412e9a14SMatthew G. Knepley } 5434412e9a14SMatthew G. Knepley 5435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5436d71ae5a4SJacob Faibussowitsch { 5437efe440bfSMatthew G. Knepley PetscSection section, s; 5438efe440bfSMatthew G. Knepley Mat m; 54393e922f36SToby Isaac PetscInt maxHeight; 5440dd4c3f67SMatthew G. Knepley const char *prefix; 5441552f7358SJed Brown 5442552f7358SJed Brown PetscFunctionBegin; 54439566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5444dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5445dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5446dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 54479566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 54489566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 54499566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 54509566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 54519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 54529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 54539566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 54549566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 54559566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 54569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 54578f4c458bSMatthew G. Knepley 54589566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 54599566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5460dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5461dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 54623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5463552f7358SJed Brown } 5464552f7358SJed Brown 5465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5466d71ae5a4SJacob Faibussowitsch { 54676858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 54686858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5469f19dbd58SToby Isaac 5470f19dbd58SToby Isaac PetscFunctionBegin; 5471f19dbd58SToby Isaac *field = NULL; 54729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 54739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 54746858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 54756858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5476f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 54776858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 54786858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5479f19dbd58SToby Isaac } 54803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5481f19dbd58SToby Isaac } 5482f19dbd58SToby Isaac 54837cd05799SMatthew G. Knepley /*@C 54847cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 54857cd05799SMatthew G. Knepley 54867cd05799SMatthew G. Knepley Not Collective 54877cd05799SMatthew G. Knepley 54882fe279fdSBarry Smith Input Parameter: 5489a1cb98faSBarry Smith . dm - The `DMPLEX` object 54907cd05799SMatthew G. Knepley 54917cd05799SMatthew G. Knepley Output Parameter: 5492a1cb98faSBarry Smith . section - The `PetscSection` object 54937cd05799SMatthew G. Knepley 54947cd05799SMatthew G. Knepley Level: developer 54957cd05799SMatthew G. Knepley 54961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 54977cd05799SMatthew G. Knepley @*/ 5498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5499d71ae5a4SJacob Faibussowitsch { 5500552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5501552f7358SJed Brown 5502552f7358SJed Brown PetscFunctionBegin; 5503552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5504552f7358SJed Brown if (section) *section = mesh->coneSection; 55053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5506552f7358SJed Brown } 5507552f7358SJed Brown 55087cd05799SMatthew G. Knepley /*@C 55097cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55107cd05799SMatthew G. Knepley 55117cd05799SMatthew G. Knepley Not Collective 55127cd05799SMatthew G. Knepley 55132fe279fdSBarry Smith Input Parameter: 5514a1cb98faSBarry Smith . dm - The `DMPLEX` object 55157cd05799SMatthew G. Knepley 55167cd05799SMatthew G. Knepley Output Parameter: 5517a1cb98faSBarry Smith . section - The `PetscSection` object 55187cd05799SMatthew G. Knepley 55197cd05799SMatthew G. Knepley Level: developer 55207cd05799SMatthew G. Knepley 55211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 55227cd05799SMatthew G. Knepley @*/ 5523d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5524d71ae5a4SJacob Faibussowitsch { 55258cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 55268cb4d582SMatthew G. Knepley 55278cb4d582SMatthew G. Knepley PetscFunctionBegin; 55288cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55298cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 55303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55318cb4d582SMatthew G. Knepley } 55328cb4d582SMatthew G. Knepley 55337cd05799SMatthew G. Knepley /*@C 55347cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 55357cd05799SMatthew G. Knepley 55367cd05799SMatthew G. Knepley Not Collective 55377cd05799SMatthew G. Knepley 55382fe279fdSBarry Smith Input Parameter: 5539a1cb98faSBarry Smith . dm - The `DMPLEX` object 55407cd05799SMatthew G. Knepley 55417cd05799SMatthew G. Knepley Output Parameter: 55427cd05799SMatthew G. Knepley . cones - The cone for each point 55437cd05799SMatthew G. Knepley 55447cd05799SMatthew G. Knepley Level: developer 55457cd05799SMatthew G. Knepley 55461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 55477cd05799SMatthew G. Knepley @*/ 5548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5549d71ae5a4SJacob Faibussowitsch { 5550552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5551552f7358SJed Brown 5552552f7358SJed Brown PetscFunctionBegin; 5553552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5554552f7358SJed Brown if (cones) *cones = mesh->cones; 55553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5556552f7358SJed Brown } 5557552f7358SJed Brown 55587cd05799SMatthew G. Knepley /*@C 55597cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 55607cd05799SMatthew G. Knepley 55617cd05799SMatthew G. Knepley Not Collective 55627cd05799SMatthew G. Knepley 55632fe279fdSBarry Smith Input Parameter: 5564a1cb98faSBarry Smith . dm - The `DMPLEX` object 55657cd05799SMatthew G. Knepley 55667cd05799SMatthew G. Knepley Output Parameter: 5567b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 55687cd05799SMatthew G. Knepley 55697cd05799SMatthew G. Knepley Level: developer 55707cd05799SMatthew G. Knepley 5571b5a892a1SMatthew G. Knepley Notes: 5572a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5573b5a892a1SMatthew G. Knepley 5574a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5575b5a892a1SMatthew G. Knepley 55761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 55777cd05799SMatthew G. Knepley @*/ 5578d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5579d71ae5a4SJacob Faibussowitsch { 5580552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5581552f7358SJed Brown 5582552f7358SJed Brown PetscFunctionBegin; 5583552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5584552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 55853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5586552f7358SJed Brown } 5587552f7358SJed Brown 5588552f7358SJed Brown /******************************** FEM Support **********************************/ 5589552f7358SJed Brown 5590d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5591d2b2dc1eSMatthew G. Knepley { 5592d2b2dc1eSMatthew G. Knepley PetscInt depth; 5593d2b2dc1eSMatthew G. Knepley 5594d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5595d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5596d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5597d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5598d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5599d2b2dc1eSMatthew G. Knepley } 5600d2b2dc1eSMatthew G. Knepley 56015962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56025962854dSMatthew G. Knepley { 56035962854dSMatthew G. Knepley PetscInt depth; 56045962854dSMatthew G. Knepley 56055962854dSMatthew G. Knepley PetscFunctionBegin; 56065962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56075962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56085962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56095962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56105962854dSMatthew G. Knepley } 56115962854dSMatthew G. Knepley 56129e8305c2SJed Brown /* 56139e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 56149e8305c2SJed Brown representing a line in the section. 56159e8305c2SJed Brown */ 5616e327e467SRezgar Shakeri static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous) 5617d71ae5a4SJacob Faibussowitsch { 5618e327e467SRezgar Shakeri PetscObject obj; 5619e327e467SRezgar Shakeri PetscClassId id; 5620e327e467SRezgar Shakeri PetscFE fe = NULL; 5621e327e467SRezgar Shakeri 56229e8305c2SJed Brown PetscFunctionBeginHot; 56239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5624e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5625e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5626e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5627e327e467SRezgar Shakeri 5628e327e467SRezgar Shakeri if (!fe) { 5629e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 56309e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 56319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 56329e8305c2SJed Brown *k = *k / *Nc + 1; 5633e327e467SRezgar Shakeri } else { 5634e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 5635e327e467SRezgar Shakeri PetscDualSpace dual_space; 5636e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 5637e327e467SRezgar Shakeri PetscCall(PetscFEGetDualSpace(fe, &dual_space)); 5638e327e467SRezgar Shakeri PetscCall(PetscDualSpaceGetDimension(dual_space, &dual_space_size)); 5639e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 5640e327e467SRezgar Shakeri PetscCall(PetscDualSpaceLagrangeGetContinuity(dual_space, continuous)); 56419e8305c2SJed Brown } 56423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56439e8305c2SJed Brown } 56449e8305c2SJed Brown 5645a4355906SMatthew Knepley /*@ 5646bc1eb3faSJed Brown 5647bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5648bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 564920f4b53cSBarry Smith section provided (or the section of the `DM`). 5650a4355906SMatthew Knepley 5651a4355906SMatthew Knepley Input Parameters: 565220f4b53cSBarry Smith + dm - The `DM` 565320f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 565420f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5655a4355906SMatthew Knepley 5656bc1eb3faSJed Brown Example: 5657bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5658bc1eb3faSJed Brown .vb 5659bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5660bc1eb3faSJed Brown 5661bc1eb3faSJed Brown v4 -- e6 -- v3 5662bc1eb3faSJed Brown | | 5663bc1eb3faSJed Brown e7 c0 e8 5664bc1eb3faSJed Brown | | 5665bc1eb3faSJed Brown v1 -- e5 -- v2 5666bc1eb3faSJed Brown .ve 5667bc1eb3faSJed Brown 5668bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5669bc1eb3faSJed Brown dofs in the order of points, e.g., 5670bc1eb3faSJed Brown .vb 5671bc1eb3faSJed Brown c0 -> [0,1,2,3] 5672bc1eb3faSJed Brown v1 -> [4] 5673bc1eb3faSJed Brown ... 5674bc1eb3faSJed Brown e5 -> [8, 9] 5675bc1eb3faSJed Brown .ve 5676bc1eb3faSJed Brown 5677bc1eb3faSJed Brown which corresponds to the dofs 5678bc1eb3faSJed Brown .vb 5679bc1eb3faSJed Brown 6 10 11 7 5680bc1eb3faSJed Brown 13 2 3 15 5681bc1eb3faSJed Brown 12 0 1 14 5682bc1eb3faSJed Brown 4 8 9 5 5683bc1eb3faSJed Brown .ve 5684bc1eb3faSJed Brown 5685bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5686bc1eb3faSJed Brown .vb 5687bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5688bc1eb3faSJed Brown .ve 5689bc1eb3faSJed Brown 5690bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5691bc1eb3faSJed Brown .vb 5692bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5693bc1eb3faSJed Brown .ve 5694bc1eb3faSJed Brown 5695a4355906SMatthew Knepley Level: developer 5696a4355906SMatthew Knepley 5697da9ac489SAlbert Cowie Notes: 5698a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5699a1cb98faSBarry Smith degree of the basis. 5700a1cb98faSBarry Smith 5701da9ac489SAlbert Cowie This is required to run with libCEED. 5702da9ac489SAlbert Cowie 57031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5704a4355906SMatthew Knepley @*/ 5705d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5706d71ae5a4SJacob Faibussowitsch { 57077391a63aSMatthew G. Knepley DMLabel label; 5708bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 5709e327e467SRezgar Shakeri PetscBool continuous = PETSC_TRUE; 57103194fc30SMatthew G. Knepley 57113194fc30SMatthew G. Knepley PetscFunctionBegin; 57129566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 57133ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5714a433471fSStefano Zampini if (point < 0) { 5715a433471fSStefano Zampini PetscInt sStart, sEnd; 5716a433471fSStefano Zampini 57179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5718a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5719a433471fSStefano Zampini } 57209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 57219566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 57229566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 57239371c9d4SSatish Balay if (depth == 1) { 57249371c9d4SSatish Balay eStart = point; 57259371c9d4SSatish Balay } else if (depth == dim) { 57267391a63aSMatthew G. Knepley const PetscInt *cone; 57277391a63aSMatthew G. Knepley 57289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5729d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5730d4e6627bSStefano Zampini else if (dim == 3) { 5731d4e6627bSStefano Zampini const PetscInt *cone2; 57329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5733d4e6627bSStefano Zampini eStart = cone2[0]; 573463a3b9bcSJacob 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); 573563a3b9bcSJacob 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); 5736e327e467SRezgar Shakeri 57379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5738bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5739bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5740bb197d40SJed Brown PetscInt *perm; 5741bb197d40SJed Brown 57423194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5743e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 5744bb197d40SJed Brown size += PetscPowInt(k + 1, d) * Nc; 57453194fc30SMatthew G. Knepley } 57469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 57473194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5748bb197d40SJed Brown switch (d) { 5749babf31e0SJed Brown case 1: 5750e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 5751babf31e0SJed Brown /* 5752babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5753babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5754babf31e0SJed Brown */ 5755e327e467SRezgar Shakeri if (continuous) { 5756babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 57579371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 57589371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5759babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5760babf31e0SJed Brown foffset = offset; 5761e327e467SRezgar Shakeri } else { 5762e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5763e327e467SRezgar Shakeri foffset = offset = size; 5764e327e467SRezgar Shakeri } 5765babf31e0SJed Brown break; 576689eabcffSMatthew G. Knepley case 2: 57673194fc30SMatthew 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} */ 5768e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 57693194fc30SMatthew G. Knepley /* The SEM order is 57703194fc30SMatthew G. Knepley 57713194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 577289eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 57733194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 57743194fc30SMatthew G. Knepley */ 5775e327e467SRezgar Shakeri if (continuous) { 57763194fc30SMatthew G. Knepley const PetscInt of = 0; 57773194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 57783194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 57793194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 57803194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 57813194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 57823194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 57833194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 57843194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 57853194fc30SMatthew G. Knepley PetscInt o; 57863194fc30SMatthew G. Knepley 57873194fc30SMatthew G. Knepley /* bottom */ 57883194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 57899371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 57909371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 57913194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 57923194fc30SMatthew G. Knepley /* middle */ 57933194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 57943194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 57959371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 57969371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 57973194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 57983194fc30SMatthew G. Knepley } 57993194fc30SMatthew G. Knepley /* top */ 58003194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 58019371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 58029371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 58033194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 58043194fc30SMatthew G. Knepley foffset = offset; 5805e327e467SRezgar Shakeri } else { 5806e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5807e327e467SRezgar Shakeri foffset = offset = size; 58083194fc30SMatthew G. Knepley } 580989eabcffSMatthew G. Knepley break; 581089eabcffSMatthew G. Knepley case 3: 581189eabcffSMatthew G. Knepley /* The original hex closure is 581289eabcffSMatthew G. Knepley 581389eabcffSMatthew G. Knepley {c, 581489eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 581589eabcffSMatthew 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, 581689eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 581789eabcffSMatthew G. Knepley */ 5818e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 581989eabcffSMatthew G. Knepley /* The SEM order is 582089eabcffSMatthew G. Knepley Bottom Slice 582189eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 582289eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 582389eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 582489eabcffSMatthew G. Knepley 582589eabcffSMatthew G. Knepley Middle Slice (j) 582689eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 582789eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 582889eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 582989eabcffSMatthew G. Knepley 583089eabcffSMatthew G. Knepley Top Slice 583189eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 583289eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 583389eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 583489eabcffSMatthew G. Knepley */ 5835e327e467SRezgar Shakeri if (continuous) { 583689eabcffSMatthew G. Knepley const PetscInt oc = 0; 583789eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 583889eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 583989eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 584089eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 584189eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 584289eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 584389eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 584489eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 584589eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 584689eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 584789eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 584889eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 584989eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 585089eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 585189eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 585289eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 585389eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 585489eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 585589eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 585689eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 585789eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 585889eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 585989eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 586089eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 586189eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 586289eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 586389eabcffSMatthew G. Knepley PetscInt o, n; 586489eabcffSMatthew G. Knepley 586589eabcffSMatthew G. Knepley /* Bottom Slice */ 586689eabcffSMatthew G. Knepley /* bottom */ 586789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 58689371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 58699371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 587089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 587189eabcffSMatthew G. Knepley /* middle */ 587289eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 587389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 58749371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 58759371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 58769371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 58779371c9d4SSatish Balay } 587889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 58793194fc30SMatthew G. Knepley } 588089eabcffSMatthew G. Knepley /* top */ 588189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 58829371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 58839371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 588489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 588589eabcffSMatthew G. Knepley 588689eabcffSMatthew G. Knepley /* Middle Slice */ 588789eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 588889eabcffSMatthew G. Knepley /* bottom */ 588989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 58909371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 58919371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 589289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 589389eabcffSMatthew G. Knepley /* middle */ 589489eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 589589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 58969371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 58979371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 589889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 589989eabcffSMatthew G. Knepley } 590089eabcffSMatthew G. Knepley /* top */ 590189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 59029371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 59039371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 590489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 590589eabcffSMatthew G. Knepley } 590689eabcffSMatthew G. Knepley 590789eabcffSMatthew G. Knepley /* Top Slice */ 590889eabcffSMatthew G. Knepley /* bottom */ 590989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 59109371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 59119371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 591289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 591389eabcffSMatthew G. Knepley /* middle */ 591489eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 591589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 59169371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 59179371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 591889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 591989eabcffSMatthew G. Knepley } 592089eabcffSMatthew G. Knepley /* top */ 592189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 59229371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 59239371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 592489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 592589eabcffSMatthew G. Knepley 592689eabcffSMatthew G. Knepley foffset = offset; 5927e327e467SRezgar Shakeri } else { 5928e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5929e327e467SRezgar Shakeri foffset = offset = size; 593089eabcffSMatthew G. Knepley } 593189eabcffSMatthew G. Knepley break; 5932d71ae5a4SJacob Faibussowitsch default: 5933d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 593489eabcffSMatthew G. Knepley } 593589eabcffSMatthew G. Knepley } 593663a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 59373194fc30SMatthew G. Knepley /* Check permutation */ 59383194fc30SMatthew G. Knepley { 59393194fc30SMatthew G. Knepley PetscInt *check; 59403194fc30SMatthew G. Knepley 59419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 59421dca8a05SBarry Smith for (i = 0; i < size; ++i) { 59431dca8a05SBarry Smith check[i] = -1; 59441dca8a05SBarry 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]); 59451dca8a05SBarry Smith } 59463194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 59471dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 59489566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 59493194fc30SMatthew G. Knepley } 59509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 5951a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 5952a05c9aa3SJed Brown PetscInt *loc_perm; 59539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 5954a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 5955a05c9aa3SJed Brown loc_perm[i] = perm[i]; 5956a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 5957a05c9aa3SJed Brown } 59589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 5959a05c9aa3SJed Brown } 5960bb197d40SJed Brown } 59613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59623194fc30SMatthew G. Knepley } 59633194fc30SMatthew G. Knepley 5964d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 5965d71ae5a4SJacob Faibussowitsch { 5966e071409bSToby Isaac PetscDS prob; 5967e071409bSToby Isaac PetscInt depth, Nf, h; 5968e071409bSToby Isaac DMLabel label; 5969e071409bSToby Isaac 5970e071409bSToby Isaac PetscFunctionBeginHot; 59719566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 5972e071409bSToby Isaac Nf = prob->Nf; 5973e071409bSToby Isaac label = dm->depthLabel; 5974e071409bSToby Isaac *dspace = NULL; 5975e071409bSToby Isaac if (field < Nf) { 5976e071409bSToby Isaac PetscObject disc = prob->disc[field]; 5977e071409bSToby Isaac 5978e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 5979e071409bSToby Isaac PetscDualSpace dsp; 5980e071409bSToby Isaac 59819566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 59829566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 59839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 5984e071409bSToby Isaac h = depth - 1 - h; 5985e071409bSToby Isaac if (h) { 59869566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 5987e071409bSToby Isaac } else { 5988e071409bSToby Isaac *dspace = dsp; 5989e071409bSToby Isaac } 5990e071409bSToby Isaac } 5991e071409bSToby Isaac } 59923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5993e071409bSToby Isaac } 5994e071409bSToby Isaac 5995d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 5996d71ae5a4SJacob Faibussowitsch { 599728351e22SJed Brown PetscScalar *array; 599828351e22SJed Brown const PetscScalar *vArray; 5999d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 60001a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6001552f7358SJed Brown 60021b406b76SMatthew G. Knepley PetscFunctionBeginHot; 60039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 60049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 60059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 60069566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 60073f7cbbe7SMatthew G. Knepley if (!values || !*values) { 60089df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 60099df71ca4SMatthew G. Knepley PetscInt dof; 6010d9917b9dSMatthew G. Knepley 60119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 60129df71ca4SMatthew G. Knepley size += dof; 60139df71ca4SMatthew G. Knepley } 60149df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 60159df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 60162a3aaacfSMatthew G. Knepley PetscInt dof; 60175a1bb5cfSMatthew G. Knepley 60185a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 60199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 60205a1bb5cfSMatthew G. Knepley size += dof; 60215a1bb5cfSMatthew G. Knepley } 60223f7cbbe7SMatthew G. Knepley if (!values) { 60233f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 60243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60253f7cbbe7SMatthew G. Knepley } 60269566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6027982e9ed1SMatthew G. Knepley } else { 6028982e9ed1SMatthew G. Knepley array = *values; 6029982e9ed1SMatthew G. Knepley } 60309df71ca4SMatthew G. Knepley size = 0; 603128351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 60329df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 60339df71ca4SMatthew G. Knepley PetscInt dof, off, d; 603428351e22SJed Brown const PetscScalar *varr; 6035d9917b9dSMatthew G. Knepley 60369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 60379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 60389df71ca4SMatthew G. Knepley varr = &vArray[off]; 6039ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 60409df71ca4SMatthew G. Knepley size += dof; 60419df71ca4SMatthew G. Knepley } 60429df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 60439df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 60449df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 60455a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 604628351e22SJed Brown const PetscScalar *varr; 60475a1bb5cfSMatthew G. Knepley 604852ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 60499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 60509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 60515a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 60525a1bb5cfSMatthew G. Knepley if (o >= 0) { 6053ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 60545a1bb5cfSMatthew G. Knepley } else { 6055ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 60565a1bb5cfSMatthew G. Knepley } 60579df71ca4SMatthew G. Knepley size += dof; 60585a1bb5cfSMatthew G. Knepley } 605928351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 60609df71ca4SMatthew G. Knepley if (!*values) { 60615a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 60625a1bb5cfSMatthew G. Knepley *values = array; 60639df71ca4SMatthew G. Knepley } else { 606463a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 60658c312ff3SMatthew G. Knepley *csize = size; 60669df71ca4SMatthew G. Knepley } 60673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60685a1bb5cfSMatthew G. Knepley } 6069d9917b9dSMatthew G. Knepley 607027f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6071d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6072d71ae5a4SJacob Faibussowitsch { 607327f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 607427f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 607527f02ce8SMatthew G. Knepley 60769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 607727f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 607827f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 607927f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 608027f02ce8SMatthew G. Knepley points[q * 2] = r; 608127f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 608227f02ce8SMatthew G. Knepley ++q; 608327f02ce8SMatthew G. Knepley } 608427f02ce8SMatthew G. Knepley } 608527f02ce8SMatthew G. Knepley *numPoints = q; 60863ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 608727f02ce8SMatthew G. Knepley } 608827f02ce8SMatthew G. Knepley 608997529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 609007218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6091d71ae5a4SJacob Faibussowitsch { 609227f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6093923c78e0SToby Isaac PetscInt np, *pts = NULL; 6094923c78e0SToby Isaac 6095923c78e0SToby Isaac PetscFunctionBeginHot; 60969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 609707218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6098923c78e0SToby Isaac PetscInt dof, off; 6099923c78e0SToby Isaac 61009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 61019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 61029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6103923c78e0SToby Isaac np = dof / 2; 6104923c78e0SToby Isaac pts = (PetscInt *)&cla[off]; 610527f02ce8SMatthew G. Knepley } else { 610607218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 61079566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6108923c78e0SToby Isaac } 6109923c78e0SToby Isaac *numPoints = np; 6110923c78e0SToby Isaac *points = pts; 6111923c78e0SToby Isaac *clp = cla; 61123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6113923c78e0SToby Isaac } 6114923c78e0SToby Isaac 6115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6116d71ae5a4SJacob Faibussowitsch { 6117923c78e0SToby Isaac PetscFunctionBeginHot; 6118923c78e0SToby Isaac if (!*clPoints) { 61199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6120923c78e0SToby Isaac } else { 61219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6122923c78e0SToby Isaac } 6123923c78e0SToby Isaac *numPoints = 0; 6124923c78e0SToby Isaac *points = NULL; 6125923c78e0SToby Isaac *clSec = NULL; 6126923c78e0SToby Isaac *clPoints = NULL; 6127923c78e0SToby Isaac *clp = NULL; 61283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6129923c78e0SToby Isaac } 6130923c78e0SToby Isaac 6131d71ae5a4SJacob 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[]) 6132d71ae5a4SJacob Faibussowitsch { 61331a271a75SMatthew G. Knepley PetscInt offset = 0, p; 613497e99dd9SToby Isaac const PetscInt **perms = NULL; 613597e99dd9SToby Isaac const PetscScalar **flips = NULL; 61361a271a75SMatthew G. Knepley 61371a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6138fe02ba77SJed Brown *size = 0; 61399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 614097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 614197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 614297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 614397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 61441a271a75SMatthew G. Knepley PetscInt dof, off, d; 61451a271a75SMatthew G. Knepley const PetscScalar *varr; 61461a271a75SMatthew G. Knepley 61479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61491a271a75SMatthew G. Knepley varr = &vArray[off]; 615097e99dd9SToby Isaac if (clperm) { 615197e99dd9SToby Isaac if (perm) { 615297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 61531a271a75SMatthew G. Knepley } else { 615497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 615597e99dd9SToby Isaac } 615697e99dd9SToby Isaac if (flip) { 615797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 615897e99dd9SToby Isaac } 615997e99dd9SToby Isaac } else { 616097e99dd9SToby Isaac if (perm) { 616197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 616297e99dd9SToby Isaac } else { 616397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 616497e99dd9SToby Isaac } 616597e99dd9SToby Isaac if (flip) { 616697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 61671a271a75SMatthew G. Knepley } 61681a271a75SMatthew G. Knepley } 616997e99dd9SToby Isaac offset += dof; 617097e99dd9SToby Isaac } 61719566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 61721a271a75SMatthew G. Knepley *size = offset; 61733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61741a271a75SMatthew G. Knepley } 61751a271a75SMatthew G. Knepley 6176d71ae5a4SJacob 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[]) 6177d71ae5a4SJacob Faibussowitsch { 61781a271a75SMatthew G. Knepley PetscInt offset = 0, f; 61791a271a75SMatthew G. Knepley 61801a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6181fe02ba77SJed Brown *size = 0; 61821a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 618397e99dd9SToby Isaac PetscInt p; 618497e99dd9SToby Isaac const PetscInt **perms = NULL; 618597e99dd9SToby Isaac const PetscScalar **flips = NULL; 61861a271a75SMatthew G. Knepley 61879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 618897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 618997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 619097e99dd9SToby Isaac PetscInt fdof, foff, b; 61911a271a75SMatthew G. Knepley const PetscScalar *varr; 619297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 619397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 61941a271a75SMatthew G. Knepley 61959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 61969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 61971a271a75SMatthew G. Knepley varr = &vArray[foff]; 619897e99dd9SToby Isaac if (clperm) { 61999371c9d4SSatish Balay if (perm) { 6200ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 62011a271a75SMatthew G. Knepley } else { 6202ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 62039371c9d4SSatish Balay } 62049371c9d4SSatish Balay if (flip) { 6205ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 62069371c9d4SSatish Balay } 62079371c9d4SSatish Balay } else { 62089371c9d4SSatish Balay if (perm) { 6209ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 62109371c9d4SSatish Balay } else { 6211ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 62129371c9d4SSatish Balay } 62139371c9d4SSatish Balay if (flip) { 6214ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 62159371c9d4SSatish Balay } 62161a271a75SMatthew G. Knepley } 621797e99dd9SToby Isaac offset += fdof; 62181a271a75SMatthew G. Knepley } 62199566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 62201a271a75SMatthew G. Knepley } 62211a271a75SMatthew G. Knepley *size = offset; 62223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62231a271a75SMatthew G. Knepley } 62241a271a75SMatthew G. Knepley 6225e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 622607218a29SMatthew G. Knepley { 622707218a29SMatthew G. Knepley PetscSection clSection; 622807218a29SMatthew G. Knepley IS clPoints; 622907218a29SMatthew G. Knepley PetscInt *points = NULL; 6230e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 623107218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 623207218a29SMatthew G. Knepley 623307218a29SMatthew G. Knepley PetscFunctionBeginHot; 623407218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 623507218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 623607218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6237e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 623807218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 623907218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 624007218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 624107218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 624207218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 624307218a29SMatthew G. Knepley } 624407218a29SMatthew G. Knepley /* Get points */ 624507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 624607218a29SMatthew G. Knepley /* Get sizes */ 624707218a29SMatthew G. Knepley asize = 0; 624807218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 624907218a29SMatthew G. Knepley PetscInt dof; 625007218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 625107218a29SMatthew G. Knepley asize += dof; 625207218a29SMatthew G. Knepley } 625307218a29SMatthew G. Knepley if (values) { 625407218a29SMatthew G. Knepley const PetscScalar *vArray; 625507218a29SMatthew G. Knepley PetscInt size; 625607218a29SMatthew G. Knepley 625707218a29SMatthew G. Knepley if (*values) { 625807218a29SMatthew 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); 625907218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6260e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 626107218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 626207218a29SMatthew G. Knepley /* Get values */ 626307218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 626407218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 626507218a29SMatthew 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); 626607218a29SMatthew G. Knepley /* Cleanup array */ 626707218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 626807218a29SMatthew G. Knepley } 626907218a29SMatthew G. Knepley if (csize) *csize = asize; 627007218a29SMatthew G. Knepley /* Cleanup points */ 627107218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 627207218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 627307218a29SMatthew G. Knepley } 627407218a29SMatthew G. Knepley 6275552f7358SJed Brown /*@C 6276552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6277552f7358SJed Brown 6278552f7358SJed Brown Not collective 6279552f7358SJed Brown 6280552f7358SJed Brown Input Parameters: 6281a1cb98faSBarry Smith + dm - The `DM` 628220f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6283552f7358SJed Brown . v - The local vector 6284a1cb98faSBarry Smith - point - The point in the `DM` 6285552f7358SJed Brown 62866b867d5aSJose E. Roman Input/Output Parameters: 628720f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 628820f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 628920f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 629022c1ee49SMatthew G. Knepley 6291552f7358SJed Brown Level: intermediate 6292552f7358SJed Brown 6293a1cb98faSBarry Smith Notes: 629420f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6295a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6296a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6297a1cb98faSBarry Smith 6298a1cb98faSBarry Smith A typical use could be 6299a1cb98faSBarry Smith .vb 6300a1cb98faSBarry Smith values = NULL; 6301a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6302a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6303a1cb98faSBarry Smith <Compute on closure> 6304a1cb98faSBarry Smith } 6305a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6306a1cb98faSBarry Smith .ve 6307a1cb98faSBarry Smith or 6308a1cb98faSBarry Smith .vb 6309a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6310a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6311a1cb98faSBarry Smith clSize = clMaxSize; 6312a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6313a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6314a1cb98faSBarry Smith <Compute on closure> 6315a1cb98faSBarry Smith } 6316a1cb98faSBarry Smith } 6317a1cb98faSBarry Smith PetscFree(values); 6318a1cb98faSBarry Smith .ve 6319a1cb98faSBarry Smith 632060225df5SJacob Faibussowitsch Fortran Notes: 632120f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6322a1cb98faSBarry Smith 63231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6324552f7358SJed Brown @*/ 6325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6326d71ae5a4SJacob Faibussowitsch { 6327d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6328e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 63293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6330552f7358SJed Brown } 6331552f7358SJed Brown 6332d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6333d71ae5a4SJacob Faibussowitsch { 6334e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6335e5c487bfSMatthew G. Knepley PetscSection clSection; 6336e5c487bfSMatthew G. Knepley IS clPoints; 6337e5c487bfSMatthew G. Knepley PetscScalar *array; 6338e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6339e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6340c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6341c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6342e5c487bfSMatthew G. Knepley 6343e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6344e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 63459566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6346e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6347e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 63489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 63499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 63509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6351e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 63529566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 63533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6354e5c487bfSMatthew G. Knepley } 6355e5c487bfSMatthew G. Knepley /* Get points */ 635607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6357c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6358c459fbc1SJed Brown PetscInt dof; 63599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6360c459fbc1SJed Brown clsize += dof; 6361c459fbc1SJed Brown } 63629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6363e5c487bfSMatthew G. Knepley /* Filter points */ 6364e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6365e5c487bfSMatthew G. Knepley PetscInt dep; 6366e5c487bfSMatthew G. Knepley 63679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6368e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6369e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6370e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6371e5c487bfSMatthew G. Knepley ++Np; 6372e5c487bfSMatthew G. Knepley } 6373e5c487bfSMatthew G. Knepley /* Get array */ 6374e5c487bfSMatthew G. Knepley if (!values || !*values) { 6375e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6376e5c487bfSMatthew G. Knepley 6377e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 63789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6379e5c487bfSMatthew G. Knepley asize += dof; 6380e5c487bfSMatthew G. Knepley } 6381e5c487bfSMatthew G. Knepley if (!values) { 63829566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6383e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 63843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6385e5c487bfSMatthew G. Knepley } 63869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6387e5c487bfSMatthew G. Knepley } else { 6388e5c487bfSMatthew G. Knepley array = *values; 6389e5c487bfSMatthew G. Knepley } 63909566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6391e5c487bfSMatthew G. Knepley /* Get values */ 63929566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 63939566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6394e5c487bfSMatthew G. Knepley /* Cleanup points */ 63959566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6396e5c487bfSMatthew G. Knepley /* Cleanup array */ 63979566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6398e5c487bfSMatthew G. Knepley if (!*values) { 6399e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6400e5c487bfSMatthew G. Knepley *values = array; 6401e5c487bfSMatthew G. Knepley } else { 640263a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6403e5c487bfSMatthew G. Knepley *csize = size; 6404e5c487bfSMatthew G. Knepley } 64053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6406e5c487bfSMatthew G. Knepley } 6407e5c487bfSMatthew G. Knepley 6408552f7358SJed Brown /*@C 6409552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6410552f7358SJed Brown 6411552f7358SJed Brown Not collective 6412552f7358SJed Brown 6413552f7358SJed Brown Input Parameters: 6414a1cb98faSBarry Smith + dm - The `DM` 641520f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6416552f7358SJed Brown . v - The local vector 6417a1cb98faSBarry Smith . point - The point in the `DM` 641820f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6419552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6420552f7358SJed Brown 6421552f7358SJed Brown Level: intermediate 6422552f7358SJed Brown 6423a1cb98faSBarry Smith Note: 642420f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6425a1cb98faSBarry Smith 642660225df5SJacob Faibussowitsch Fortran Notes: 642720f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6428a1cb98faSBarry Smith 64291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6430552f7358SJed Brown @*/ 6431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6432d71ae5a4SJacob Faibussowitsch { 6433552f7358SJed Brown PetscInt size = 0; 6434552f7358SJed Brown 6435552f7358SJed Brown PetscFunctionBegin; 6436552f7358SJed Brown /* Should work without recalculating size */ 64379566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6438c9fdaa05SMatthew G. Knepley *values = NULL; 64393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6440552f7358SJed Brown } 6441552f7358SJed Brown 6442d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6443d71ae5a4SJacob Faibussowitsch { 64449371c9d4SSatish Balay *x += y; 64459371c9d4SSatish Balay } 6446d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6447d71ae5a4SJacob Faibussowitsch { 64489371c9d4SSatish Balay *x = y; 64499371c9d4SSatish Balay } 6450552f7358SJed Brown 6451d71ae5a4SJacob 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[]) 6452d71ae5a4SJacob Faibussowitsch { 6453552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6454552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6455552f7358SJed Brown PetscScalar *a; 6456552f7358SJed Brown PetscInt off, cind = 0, k; 6457552f7358SJed Brown 6458552f7358SJed Brown PetscFunctionBegin; 64599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 64609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6461552f7358SJed Brown a = &array[off]; 6462552f7358SJed Brown if (!cdof || setBC) { 646397e99dd9SToby Isaac if (clperm) { 64649371c9d4SSatish Balay if (perm) { 6465ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6466552f7358SJed Brown } else { 6467ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 64689371c9d4SSatish Balay } 64699371c9d4SSatish Balay } else { 64709371c9d4SSatish Balay if (perm) { 6471ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 64729371c9d4SSatish Balay } else { 6473ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 64749371c9d4SSatish Balay } 6475552f7358SJed Brown } 6476552f7358SJed Brown } else { 64779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 647897e99dd9SToby Isaac if (clperm) { 64799371c9d4SSatish Balay if (perm) { 64809371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 64819371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 64829371c9d4SSatish Balay ++cind; 64839371c9d4SSatish Balay continue; 64849371c9d4SSatish Balay } 648597e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6486552f7358SJed Brown } 6487552f7358SJed Brown } else { 6488552f7358SJed Brown for (k = 0; k < dof; ++k) { 64899371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 64909371c9d4SSatish Balay ++cind; 64919371c9d4SSatish Balay continue; 64929371c9d4SSatish Balay } 649397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 649497e99dd9SToby Isaac } 649597e99dd9SToby Isaac } 649697e99dd9SToby Isaac } else { 649797e99dd9SToby Isaac if (perm) { 649897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 64999371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65009371c9d4SSatish Balay ++cind; 65019371c9d4SSatish Balay continue; 65029371c9d4SSatish Balay } 650397e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 650497e99dd9SToby Isaac } 650597e99dd9SToby Isaac } else { 650697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 65079371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65089371c9d4SSatish Balay ++cind; 65099371c9d4SSatish Balay continue; 65109371c9d4SSatish Balay } 651197e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 651297e99dd9SToby Isaac } 6513552f7358SJed Brown } 6514552f7358SJed Brown } 6515552f7358SJed Brown } 65163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6517552f7358SJed Brown } 6518552f7358SJed Brown 6519d71ae5a4SJacob 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[]) 6520d71ae5a4SJacob Faibussowitsch { 6521a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6522a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6523a5e93ea8SMatthew G. Knepley PetscScalar *a; 6524a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6525a5e93ea8SMatthew G. Knepley 6526a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 65279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6529a5e93ea8SMatthew G. Knepley a = &array[off]; 6530a5e93ea8SMatthew G. Knepley if (cdof) { 65319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 653297e99dd9SToby Isaac if (clperm) { 653397e99dd9SToby Isaac if (perm) { 6534a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6535a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 653697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 653797e99dd9SToby Isaac cind++; 6538a5e93ea8SMatthew G. Knepley } 6539a5e93ea8SMatthew G. Knepley } 6540a5e93ea8SMatthew G. Knepley } else { 6541a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6542a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 654397e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 654497e99dd9SToby Isaac cind++; 654597e99dd9SToby Isaac } 654697e99dd9SToby Isaac } 654797e99dd9SToby Isaac } 654897e99dd9SToby Isaac } else { 654997e99dd9SToby Isaac if (perm) { 655097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 655197e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 655297e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 655397e99dd9SToby Isaac cind++; 655497e99dd9SToby Isaac } 655597e99dd9SToby Isaac } 655697e99dd9SToby Isaac } else { 655797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 655897e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 655997e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 656097e99dd9SToby Isaac cind++; 656197e99dd9SToby Isaac } 6562a5e93ea8SMatthew G. Knepley } 6563a5e93ea8SMatthew G. Knepley } 6564a5e93ea8SMatthew G. Knepley } 6565a5e93ea8SMatthew G. Knepley } 65663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6567a5e93ea8SMatthew G. Knepley } 6568a5e93ea8SMatthew G. Knepley 6569d71ae5a4SJacob 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[]) 6570d71ae5a4SJacob Faibussowitsch { 6571552f7358SJed Brown PetscScalar *a; 65721a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 65731a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 657497e99dd9SToby Isaac PetscInt cind = 0, b; 6575552f7358SJed Brown 6576552f7358SJed Brown PetscFunctionBegin; 65779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 65789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 65799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 65801a271a75SMatthew G. Knepley a = &array[foff]; 6581552f7358SJed Brown if (!fcdof || setBC) { 658297e99dd9SToby Isaac if (clperm) { 65839371c9d4SSatish Balay if (perm) { 6584ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6585552f7358SJed Brown } else { 6586ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 65879371c9d4SSatish Balay } 65889371c9d4SSatish Balay } else { 65899371c9d4SSatish Balay if (perm) { 6590ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 65919371c9d4SSatish Balay } else { 6592ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 65939371c9d4SSatish Balay } 6594552f7358SJed Brown } 6595552f7358SJed Brown } else { 65969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 659797e99dd9SToby Isaac if (clperm) { 659897e99dd9SToby Isaac if (perm) { 659997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66009371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66019371c9d4SSatish Balay ++cind; 66029371c9d4SSatish Balay continue; 66039371c9d4SSatish Balay } 660497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6605552f7358SJed Brown } 6606552f7358SJed Brown } else { 660797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66089371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66099371c9d4SSatish Balay ++cind; 66109371c9d4SSatish Balay continue; 66119371c9d4SSatish Balay } 661297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 661397e99dd9SToby Isaac } 661497e99dd9SToby Isaac } 661597e99dd9SToby Isaac } else { 661697e99dd9SToby Isaac if (perm) { 661797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66189371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66199371c9d4SSatish Balay ++cind; 66209371c9d4SSatish Balay continue; 66219371c9d4SSatish Balay } 662297e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 662397e99dd9SToby Isaac } 662497e99dd9SToby Isaac } else { 662597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66269371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66279371c9d4SSatish Balay ++cind; 66289371c9d4SSatish Balay continue; 66299371c9d4SSatish Balay } 663097e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6631552f7358SJed Brown } 6632552f7358SJed Brown } 6633552f7358SJed Brown } 6634552f7358SJed Brown } 66351a271a75SMatthew G. Knepley *offset += fdof; 66363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6637552f7358SJed Brown } 6638552f7358SJed Brown 6639d71ae5a4SJacob 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[]) 6640d71ae5a4SJacob Faibussowitsch { 6641a5e93ea8SMatthew G. Knepley PetscScalar *a; 66421a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 66431a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 66445da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6645ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6646a5e93ea8SMatthew G. Knepley 6647a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 66499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 66519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 66521a271a75SMatthew G. Knepley a = &array[foff]; 6653a5e93ea8SMatthew G. Knepley if (fcdof) { 6654ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 66559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 665697e99dd9SToby Isaac if (clperm) { 665797e99dd9SToby Isaac if (perm) { 6658ba322698SMatthew G. Knepley if (comps) { 6659ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6660ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 66619371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 66629371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 66639371c9d4SSatish Balay ncSet = PETSC_TRUE; 66649371c9d4SSatish Balay } 66659371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66669371c9d4SSatish Balay ++cind; 66679371c9d4SSatish Balay fcSet = PETSC_TRUE; 66689371c9d4SSatish Balay } 6669ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6670ba322698SMatthew G. Knepley } 6671ba322698SMatthew G. Knepley } else { 667297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 667397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 667497e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6675a5e93ea8SMatthew G. Knepley ++cind; 6676a5e93ea8SMatthew G. Knepley } 6677a5e93ea8SMatthew G. Knepley } 6678ba322698SMatthew G. Knepley } 6679ba322698SMatthew G. Knepley } else { 6680ba322698SMatthew G. Knepley if (comps) { 6681ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6682ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 66839371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 66849371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 66859371c9d4SSatish Balay ncSet = PETSC_TRUE; 66869371c9d4SSatish Balay } 66879371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66889371c9d4SSatish Balay ++cind; 66899371c9d4SSatish Balay fcSet = PETSC_TRUE; 66909371c9d4SSatish Balay } 6691ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6692ba322698SMatthew G. Knepley } 6693a5e93ea8SMatthew G. Knepley } else { 669497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 669597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 669697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 669797e99dd9SToby Isaac ++cind; 669897e99dd9SToby Isaac } 669997e99dd9SToby Isaac } 670097e99dd9SToby Isaac } 6701ba322698SMatthew G. Knepley } 670297e99dd9SToby Isaac } else { 670397e99dd9SToby Isaac if (perm) { 6704ba322698SMatthew G. Knepley if (comps) { 6705ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6706ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67079371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67089371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67099371c9d4SSatish Balay ncSet = PETSC_TRUE; 67109371c9d4SSatish Balay } 67119371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67129371c9d4SSatish Balay ++cind; 67139371c9d4SSatish Balay fcSet = PETSC_TRUE; 67149371c9d4SSatish Balay } 6715ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6716ba322698SMatthew G. Knepley } 6717ba322698SMatthew G. Knepley } else { 671897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 671997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 672097e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 672197e99dd9SToby Isaac ++cind; 672297e99dd9SToby Isaac } 672397e99dd9SToby Isaac } 6724ba322698SMatthew G. Knepley } 6725ba322698SMatthew G. Knepley } else { 6726ba322698SMatthew G. Knepley if (comps) { 6727ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6728ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67299371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67309371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67319371c9d4SSatish Balay ncSet = PETSC_TRUE; 67329371c9d4SSatish Balay } 67339371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67349371c9d4SSatish Balay ++cind; 67359371c9d4SSatish Balay fcSet = PETSC_TRUE; 67369371c9d4SSatish Balay } 6737ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6738ba322698SMatthew G. Knepley } 673997e99dd9SToby Isaac } else { 674097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 674197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 674297e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6743a5e93ea8SMatthew G. Knepley ++cind; 6744a5e93ea8SMatthew G. Knepley } 6745a5e93ea8SMatthew G. Knepley } 6746a5e93ea8SMatthew G. Knepley } 6747a5e93ea8SMatthew G. Knepley } 6748a5e93ea8SMatthew G. Knepley } 6749ba322698SMatthew G. Knepley } 67501a271a75SMatthew G. Knepley *offset += fdof; 67513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6752a5e93ea8SMatthew G. Knepley } 6753a5e93ea8SMatthew G. Knepley 6754d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6755d71ae5a4SJacob Faibussowitsch { 6756552f7358SJed Brown PetscScalar *array; 67571b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 67581b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6759552f7358SJed Brown 67601b406b76SMatthew G. Knepley PetscFunctionBeginHot; 67619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 67629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 67639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 67649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 67659566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6766b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6767b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6768b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6769b6ebb6e6SMatthew G. Knepley 67709371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 67719371c9d4SSatish Balay dof = 0; 67729371c9d4SSatish Balay continue; 67739371c9d4SSatish Balay } 67749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6775b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6776b6ebb6e6SMatthew G. Knepley { 6777b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6778b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6779b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6780b6ebb6e6SMatthew G. Knepley 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6783b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6784b6ebb6e6SMatthew G. Knepley if (!cdof) { 6785b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6786ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6787b6ebb6e6SMatthew G. Knepley } else { 6788ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6789b6ebb6e6SMatthew G. Knepley } 6790b6ebb6e6SMatthew G. Knepley } else { 67919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6792b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6793b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 67949371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 67959371c9d4SSatish Balay ++cind; 67969371c9d4SSatish Balay continue; 67979371c9d4SSatish Balay } 6798b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6799b6ebb6e6SMatthew G. Knepley } 6800b6ebb6e6SMatthew G. Knepley } else { 6801b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 68029371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 68039371c9d4SSatish Balay ++cind; 68049371c9d4SSatish Balay continue; 68059371c9d4SSatish Balay } 6806b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6807b6ebb6e6SMatthew G. Knepley } 6808b6ebb6e6SMatthew G. Knepley } 6809b6ebb6e6SMatthew G. Knepley } 6810b6ebb6e6SMatthew G. Knepley } 6811b6ebb6e6SMatthew G. Knepley } 68129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 68133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6814b6ebb6e6SMatthew G. Knepley } 68151b406b76SMatthew G. Knepley 68161b406b76SMatthew G. Knepley /*@C 681720f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 68181b406b76SMatthew G. Knepley 68191b406b76SMatthew G. Knepley Not collective 68201b406b76SMatthew G. Knepley 68211b406b76SMatthew G. Knepley Input Parameters: 6822a1cb98faSBarry Smith + dm - The `DM` 682320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 68241b406b76SMatthew G. Knepley . v - The local vector 682520f4b53cSBarry Smith . point - The point in the `DM` 68261b406b76SMatthew G. Knepley . values - The array of values 6827a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6828a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 68291b406b76SMatthew G. Knepley 68301b406b76SMatthew G. Knepley Level: intermediate 68311b406b76SMatthew G. Knepley 68321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 68331b406b76SMatthew G. Knepley @*/ 6834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6835d71ae5a4SJacob Faibussowitsch { 68361b406b76SMatthew G. Knepley PetscSection clSection; 68371b406b76SMatthew G. Knepley IS clPoints; 68381b406b76SMatthew G. Knepley PetscScalar *array; 68391b406b76SMatthew G. Knepley PetscInt *points = NULL; 684027f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6841c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 68421b406b76SMatthew G. Knepley 68431a271a75SMatthew G. Knepley PetscFunctionBeginHot; 68441b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 68459566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 68461a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 68471a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 68489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 68499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 68501b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 68519566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 68523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68531b406b76SMatthew G. Knepley } 68541a271a75SMatthew G. Knepley /* Get points */ 685507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6856c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6857c459fbc1SJed Brown PetscInt dof; 68589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6859c459fbc1SJed Brown clsize += dof; 6860c459fbc1SJed Brown } 68619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 68621a271a75SMatthew G. Knepley /* Get array */ 68639566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 68641a271a75SMatthew G. Knepley /* Get values */ 6865ef90cfe2SMatthew G. Knepley if (numFields > 0) { 686697e99dd9SToby Isaac PetscInt offset = 0, f; 6867552f7358SJed Brown for (f = 0; f < numFields; ++f) { 686897e99dd9SToby Isaac const PetscInt **perms = NULL; 686997e99dd9SToby Isaac const PetscScalar **flips = NULL; 687097e99dd9SToby Isaac 68719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6872552f7358SJed Brown switch (mode) { 6873552f7358SJed Brown case INSERT_VALUES: 687497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 687597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 687697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 687797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 68783ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 68799371c9d4SSatish Balay } 68809371c9d4SSatish Balay break; 6881552f7358SJed Brown case INSERT_ALL_VALUES: 688297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 688397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 688497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 688597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 68863ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 68879371c9d4SSatish Balay } 68889371c9d4SSatish Balay break; 6889a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 689097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 689197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 689297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 689397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 68943ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 68959371c9d4SSatish Balay } 68969371c9d4SSatish Balay break; 6897552f7358SJed Brown case ADD_VALUES: 689897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 689997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 690097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 690197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69023ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 69039371c9d4SSatish Balay } 69049371c9d4SSatish Balay break; 6905552f7358SJed Brown case ADD_ALL_VALUES: 690697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 690797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 690897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 690997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69103ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 69119371c9d4SSatish Balay } 69129371c9d4SSatish Balay break; 6913304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 691497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 691597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 691697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 691797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69183ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 69199371c9d4SSatish Balay } 69209371c9d4SSatish Balay break; 6921d71ae5a4SJacob Faibussowitsch default: 6922d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6923552f7358SJed Brown } 69249566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 69251a271a75SMatthew G. Knepley } 6926552f7358SJed Brown } else { 69271a271a75SMatthew G. Knepley PetscInt dof, off; 692897e99dd9SToby Isaac const PetscInt **perms = NULL; 692997e99dd9SToby Isaac const PetscScalar **flips = NULL; 69301a271a75SMatthew G. Knepley 69319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 6932552f7358SJed Brown switch (mode) { 6933552f7358SJed Brown case INSERT_VALUES: 693497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 693597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 693697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 693797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69393ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 69409371c9d4SSatish Balay } 69419371c9d4SSatish Balay break; 6942552f7358SJed Brown case INSERT_ALL_VALUES: 694397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 694497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 694597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 694697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69483ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 69499371c9d4SSatish Balay } 69509371c9d4SSatish Balay break; 6951a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 695297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 695397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 695497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 695597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69573ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 69589371c9d4SSatish Balay } 69599371c9d4SSatish Balay break; 6960552f7358SJed Brown case ADD_VALUES: 696197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 696297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 696397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 696497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69663ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 69679371c9d4SSatish Balay } 69689371c9d4SSatish Balay break; 6969552f7358SJed Brown case ADD_ALL_VALUES: 697097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 697197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 697297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 697397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69753ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 69769371c9d4SSatish Balay } 69779371c9d4SSatish Balay break; 6978304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 697997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 698097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 698197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 698297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69843ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 69859371c9d4SSatish Balay } 69869371c9d4SSatish Balay break; 6987d71ae5a4SJacob Faibussowitsch default: 6988d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6989552f7358SJed Brown } 69909566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 6991552f7358SJed Brown } 69921a271a75SMatthew G. Knepley /* Cleanup points */ 69939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 69941a271a75SMatthew G. Knepley /* Cleanup array */ 69959566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6997552f7358SJed Brown } 6998552f7358SJed Brown 69995f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7000d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7001d71ae5a4SJacob Faibussowitsch { 70025f790a90SMatthew G. Knepley PetscFunctionBegin; 700311cc89d2SBarry Smith *contains = PETSC_TRUE; 70045f790a90SMatthew G. Knepley if (label) { 7005d6177c40SToby Isaac PetscInt fdof; 70065f790a90SMatthew G. Knepley 700711cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 700811cc89d2SBarry Smith if (!*contains) { 70099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70105f790a90SMatthew G. Knepley *offset += fdof; 70113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70125f790a90SMatthew G. Knepley } 70135f790a90SMatthew G. Knepley } 70143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70155f790a90SMatthew G. Knepley } 70165f790a90SMatthew G. Knepley 701797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7018d71ae5a4SJacob 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) 7019d71ae5a4SJacob Faibussowitsch { 7020e07394fbSMatthew G. Knepley PetscSection clSection; 7021e07394fbSMatthew G. Knepley IS clPoints; 7022e07394fbSMatthew G. Knepley PetscScalar *array; 7023e07394fbSMatthew G. Knepley PetscInt *points = NULL; 702497529cf3SJed Brown const PetscInt *clp; 7025e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 702697e99dd9SToby Isaac PetscInt offset = 0, f; 7027e07394fbSMatthew G. Knepley 7028e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7029e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 70309566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7031e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7032e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 70339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7034e07394fbSMatthew G. Knepley /* Get points */ 703507218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7036e07394fbSMatthew G. Knepley /* Get array */ 70379566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7038e07394fbSMatthew G. Knepley /* Get values */ 7039e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 704097e99dd9SToby Isaac const PetscInt **perms = NULL; 704197e99dd9SToby Isaac const PetscScalar **flips = NULL; 704211cc89d2SBarry Smith PetscBool contains; 704397e99dd9SToby Isaac 7044e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7045e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7046e07394fbSMatthew G. Knepley PetscInt fdof; 70479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7048e07394fbSMatthew G. Knepley offset += fdof; 7049e07394fbSMatthew G. Knepley } 7050e07394fbSMatthew G. Knepley continue; 7051e07394fbSMatthew G. Knepley } 70529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7053e07394fbSMatthew G. Knepley switch (mode) { 7054e07394fbSMatthew G. Knepley case INSERT_VALUES: 705597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 705697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 705797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 705897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 705911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 706011cc89d2SBarry Smith if (!contains) continue; 70619566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 70629371c9d4SSatish Balay } 70639371c9d4SSatish Balay break; 7064e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 706597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 706697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 706911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 707011cc89d2SBarry Smith if (!contains) continue; 70719566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 70729371c9d4SSatish Balay } 70739371c9d4SSatish Balay break; 7074e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 707597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 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; 707911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 708011cc89d2SBarry Smith if (!contains) continue; 70819566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 70829371c9d4SSatish Balay } 70839371c9d4SSatish Balay break; 7084e07394fbSMatthew G. Knepley case ADD_VALUES: 708597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 708697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 708911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 709011cc89d2SBarry Smith if (!contains) continue; 70919566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 70929371c9d4SSatish Balay } 70939371c9d4SSatish Balay break; 7094e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 709597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 709697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 709797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 709911cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 710011cc89d2SBarry Smith if (!contains) continue; 71019566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 71029371c9d4SSatish Balay } 71039371c9d4SSatish Balay break; 7104d71ae5a4SJacob Faibussowitsch default: 7105d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7106e07394fbSMatthew G. Knepley } 71079566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7108e07394fbSMatthew G. Knepley } 7109e07394fbSMatthew G. Knepley /* Cleanup points */ 71109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7111e07394fbSMatthew G. Knepley /* Cleanup array */ 71129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7114e07394fbSMatthew G. Knepley } 7115e07394fbSMatthew G. Knepley 7116d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7117d71ae5a4SJacob Faibussowitsch { 7118552f7358SJed Brown PetscMPIInt rank; 7119552f7358SJed Brown PetscInt i, j; 7120552f7358SJed Brown 7121552f7358SJed Brown PetscFunctionBegin; 71229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 712363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 712463a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 712563a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7126b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 71273ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7128b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 71299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7130b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7131519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 71329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7133552f7358SJed Brown #else 71349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7135552f7358SJed Brown #endif 7136552f7358SJed Brown } 71379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7138552f7358SJed Brown } 71393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7140552f7358SJed Brown } 7141552f7358SJed Brown 714205586334SMatthew G. Knepley /* 714305586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 714405586334SMatthew G. Knepley 714505586334SMatthew G. Knepley Input Parameters: 714605586334SMatthew G. Knepley + section - The section for this data layout 714736fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 714805586334SMatthew G. Knepley . point - The point contributing dofs with these indices 714905586334SMatthew G. Knepley . off - The global offset of this point 715005586334SMatthew G. Knepley . loff - The local offset of each field 7151a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 715205586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 715305586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 715405586334SMatthew G. Knepley 715505586334SMatthew G. Knepley Output Parameter: 715605586334SMatthew G. Knepley . indices - Indices for dofs on this point 715705586334SMatthew G. Knepley 715805586334SMatthew G. Knepley Level: developer 715905586334SMatthew G. Knepley 716005586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 716105586334SMatthew G. Knepley */ 7162d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7163d71ae5a4SJacob Faibussowitsch { 7164e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7165552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7166552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7167552f7358SJed Brown PetscInt cind = 0, k; 7168552f7358SJed Brown 7169552f7358SJed Brown PetscFunctionBegin; 717008401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 71719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7173552f7358SJed Brown if (!cdof || setBC) { 717405586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 717505586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 717605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 717705586334SMatthew G. Knepley 717805586334SMatthew G. Knepley indices[ind] = off + k; 7179552f7358SJed Brown } 7180552f7358SJed Brown } else { 71819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 71824acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 718305586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 718405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 718505586334SMatthew G. Knepley 71864acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 71874acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 718805586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 71894acb8e1eSToby Isaac ++cind; 71904acb8e1eSToby Isaac } else { 719136fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7192552f7358SJed Brown } 7193552f7358SJed Brown } 7194552f7358SJed Brown } 7195e6ccafaeSMatthew G Knepley *loff += dof; 71963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7197552f7358SJed Brown } 7198552f7358SJed Brown 71997e29afd2SMatthew G. Knepley /* 720036fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 72017e29afd2SMatthew G. Knepley 720236fa2b79SJed Brown Input Parameters: 720336fa2b79SJed Brown + section - a section (global or local) 720420f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 720536fa2b79SJed Brown . point - point within section 720636fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 720736fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 720836fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 720936fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 721036fa2b79SJed Brown . permsoff - offset 721136fa2b79SJed Brown - indperm - index permutation 721236fa2b79SJed Brown 721336fa2b79SJed Brown Output Parameter: 721436fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 721536fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 721636fa2b79SJed Brown 721736fa2b79SJed Brown Notes: 721836fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 721936fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 722036fa2b79SJed Brown in the local vector. 722136fa2b79SJed Brown 722236fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 722336fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 722436fa2b79SJed Brown 722536fa2b79SJed Brown Developer Note: 722636fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 722736fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 722836fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 722936fa2b79SJed Brown 723036fa2b79SJed Brown Example: 723136fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 723236fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 723336fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 723436fa2b79SJed 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. 723536fa2b79SJed Brown 723636fa2b79SJed Brown Level: developer 72377e29afd2SMatthew G. Knepley */ 7238d71ae5a4SJacob 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[]) 7239d71ae5a4SJacob Faibussowitsch { 7240552f7358SJed Brown PetscInt numFields, foff, f; 7241552f7358SJed Brown 7242552f7358SJed Brown PetscFunctionBegin; 724308401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 72449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7245552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 72464acb8e1eSToby Isaac PetscInt fdof, cfdof; 7247552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 72484acb8e1eSToby Isaac PetscInt cind = 0, b; 72494acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7250552f7358SJed Brown 72519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 72529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7253552f7358SJed Brown if (!cfdof || setBC) { 725405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 725505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 725605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 725705586334SMatthew G. Knepley 725805586334SMatthew G. Knepley indices[ind] = off + foff + b; 725905586334SMatthew G. Knepley } 7260552f7358SJed Brown } else { 72619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 726205586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 726305586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 726405586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 726505586334SMatthew G. Knepley 72664acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 726705586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7268552f7358SJed Brown ++cind; 7269552f7358SJed Brown } else { 727036fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7271552f7358SJed Brown } 7272552f7358SJed Brown } 7273552f7358SJed Brown } 727436fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7275552f7358SJed Brown foffs[f] += fdof; 7276552f7358SJed Brown } 72773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7278552f7358SJed Brown } 7279552f7358SJed Brown 72807e29afd2SMatthew G. Knepley /* 72817e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 72827e29afd2SMatthew G. Knepley 72837e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7284645102dcSJed Brown 7285645102dcSJed Brown Notes: 7286645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7287645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 72887e29afd2SMatthew G. Knepley */ 7289d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7290d71ae5a4SJacob Faibussowitsch { 72917e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 72927e29afd2SMatthew G. Knepley 72937e29afd2SMatthew G. Knepley PetscFunctionBegin; 72949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 72957e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 72967e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 72977e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 72987e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 72997e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 73007e29afd2SMatthew G. Knepley 73019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 73039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7304645102dcSJed Brown if (!cfdof) { 730505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 730605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 730705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730805586334SMatthew G. Knepley 730905586334SMatthew G. Knepley indices[ind] = foff + b; 731005586334SMatthew G. Knepley } 73117e29afd2SMatthew G. Knepley } else { 73129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 731305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 731405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 731505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731605586334SMatthew G. Knepley 73177e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 731805586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 73197e29afd2SMatthew G. Knepley ++cind; 73207e29afd2SMatthew G. Knepley } else { 732105586334SMatthew G. Knepley indices[ind] = foff + b - cind; 73227e29afd2SMatthew G. Knepley } 73237e29afd2SMatthew G. Knepley } 73247e29afd2SMatthew G. Knepley } 73257e29afd2SMatthew G. Knepley foffs[f] += fdof; 73267e29afd2SMatthew G. Knepley } 73273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73287e29afd2SMatthew G. Knepley } 73297e29afd2SMatthew G. Knepley 7330d71ae5a4SJacob 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) 7331d71ae5a4SJacob Faibussowitsch { 7332d3d1a6afSToby Isaac Mat cMat; 7333d3d1a6afSToby Isaac PetscSection aSec, cSec; 7334d3d1a6afSToby Isaac IS aIS; 7335d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7336d3d1a6afSToby Isaac const PetscInt *anchors; 7337e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7338d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7339d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7340d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7341d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7342d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7343d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7344d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 73456ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7346d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7347d3d1a6afSToby Isaac 7348d3d1a6afSToby Isaac PetscFunctionBegin; 7349d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7350d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 73519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7352d3d1a6afSToby Isaac 73539566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7354d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7355d3d1a6afSToby Isaac if (aSec) { 73569566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 73579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 73589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7359d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7360d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7361d3d1a6afSToby Isaac * into the global matrix anyway) */ 7362d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7363d3d1a6afSToby Isaac PetscInt b = points[p]; 73644b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7365d3d1a6afSToby Isaac 73669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7367ad540459SPierre Jolivet if (!bSecDof) continue; 736848a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7369d3d1a6afSToby Isaac if (bDof) { 7370d3d1a6afSToby Isaac /* this point is constrained */ 7371d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7372d3d1a6afSToby Isaac PetscInt bOff, q; 7373d3d1a6afSToby Isaac 7374d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7375d3d1a6afSToby Isaac newNumPoints += bDof; 73769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7377d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7378d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7379d3d1a6afSToby Isaac PetscInt aDof; 7380d3d1a6afSToby Isaac 73819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7382d3d1a6afSToby Isaac newNumIndices += aDof; 7383d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7384d3d1a6afSToby Isaac PetscInt fDof; 7385d3d1a6afSToby Isaac 73869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7387d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7388d3d1a6afSToby Isaac } 7389d3d1a6afSToby Isaac } 73909371c9d4SSatish Balay } else { 7391d3d1a6afSToby Isaac /* this point is not constrained */ 7392d3d1a6afSToby Isaac newNumPoints++; 73934b2f2278SToby Isaac newNumIndices += bSecDof; 7394d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7395d3d1a6afSToby Isaac PetscInt fDof; 7396d3d1a6afSToby Isaac 73979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7398d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7399d3d1a6afSToby Isaac } 7400d3d1a6afSToby Isaac } 7401d3d1a6afSToby Isaac } 7402d3d1a6afSToby Isaac } 7403d3d1a6afSToby Isaac if (!anyConstrained) { 740472b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 740572b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 740672b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 740772b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 74089566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 74093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7410d3d1a6afSToby Isaac } 7411d3d1a6afSToby Isaac 74126ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 74136ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 74146ecaa68aSToby Isaac 7415f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7416d3d1a6afSToby Isaac 74176ecaa68aSToby Isaac if (!outPoints && !outValues) { 74186ecaa68aSToby Isaac if (offsets) { 7419ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 74206ecaa68aSToby Isaac } 74219566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 74223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74236ecaa68aSToby Isaac } 74246ecaa68aSToby Isaac 74251dca8a05SBarry 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); 7426d3d1a6afSToby Isaac 74279566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7428d3d1a6afSToby Isaac 7429d3d1a6afSToby Isaac /* workspaces */ 7430d3d1a6afSToby Isaac if (numFields) { 7431d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 74329566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 74339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7434d3d1a6afSToby Isaac } 74359371c9d4SSatish Balay } else { 74369566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 74379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7438d3d1a6afSToby Isaac } 7439d3d1a6afSToby Isaac 7440d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7441d3d1a6afSToby Isaac if (numFields) { 74424b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 74434b2f2278SToby Isaac 7444d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7445d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 74464b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7447d3d1a6afSToby Isaac 74489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 74494b2f2278SToby Isaac if (!bSecDof) { 74504b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 74514b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 74524b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 74534b2f2278SToby Isaac } 74544b2f2278SToby Isaac continue; 74554b2f2278SToby Isaac } 745648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7457d3d1a6afSToby Isaac if (bDof) { 7458d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7459d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7460d3d1a6afSToby Isaac 74619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 74629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7463d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7464d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7465d3d1a6afSToby Isaac PetscInt aFDof; 7466d3d1a6afSToby Isaac 74679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7468d3d1a6afSToby Isaac allFDof += aFDof; 7469d3d1a6afSToby Isaac } 7470d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7471d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7472d3d1a6afSToby Isaac } 74739371c9d4SSatish Balay } else { 7474d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7475d3d1a6afSToby Isaac PetscInt fDof; 7476d3d1a6afSToby Isaac 74779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7478d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7479d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7480d3d1a6afSToby Isaac } 7481d3d1a6afSToby Isaac } 7482d3d1a6afSToby Isaac } 74834b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 74844b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 74854b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7486d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7487d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7488d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7489d3d1a6afSToby Isaac } 749019f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 749119f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 74929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7493d3d1a6afSToby Isaac } 74949371c9d4SSatish Balay } else { 7495d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7496d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 74974b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7498d3d1a6afSToby Isaac 74999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75004b2f2278SToby Isaac if (!bSecDof) { 75014b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 75024b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 75034b2f2278SToby Isaac continue; 75044b2f2278SToby Isaac } 750548a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7506d3d1a6afSToby Isaac if (bDof) { 75074b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7508d3d1a6afSToby Isaac 75099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7510d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7511d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7512d3d1a6afSToby Isaac 75139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7514d3d1a6afSToby Isaac allDof += aDof; 7515d3d1a6afSToby Isaac } 7516d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 75174b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 75189371c9d4SSatish Balay } else { 75194b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7520d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7521d3d1a6afSToby Isaac } 7522d3d1a6afSToby Isaac } 7523d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7524d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7525d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7526d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7527d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7528d3d1a6afSToby Isaac } 75299566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7530d3d1a6afSToby Isaac } 7531d3d1a6afSToby Isaac 75326ecaa68aSToby Isaac /* output arrays */ 75339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 75346ecaa68aSToby Isaac 7535d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 75369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 75379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 75389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 75399566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7540d3d1a6afSToby Isaac if (numFields) { 7541d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7542d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7543d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 75444b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7545d3d1a6afSToby Isaac 75469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7547ad540459SPierre Jolivet if (!bSecDof) continue; 754848a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7549d3d1a6afSToby Isaac if (bDof) { 7550d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7551d3d1a6afSToby Isaac 7552d3d1a6afSToby Isaac fStart[0] = 0; 7553d3d1a6afSToby Isaac fEnd[0] = 0; 7554d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7555d3d1a6afSToby Isaac PetscInt fDof; 7556d3d1a6afSToby Isaac 75579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7558d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7559d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7560d3d1a6afSToby Isaac } 75619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 75629566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7563d3d1a6afSToby Isaac 7564d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7565d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7566d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7567d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7568d3d1a6afSToby Isaac 7569d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7570d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7571d3d1a6afSToby Isaac } 75729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7573d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7574d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7575d3d1a6afSToby Isaac 7576d3d1a6afSToby 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 */ 7577d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7578d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 75799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 75809566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7581d3d1a6afSToby Isaac } 7582d3d1a6afSToby Isaac newP += bDof; 7583d3d1a6afSToby Isaac 75846ecaa68aSToby Isaac if (outValues) { 7585d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 758648a46eb9SPierre 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])); 7587d3d1a6afSToby Isaac } 75889371c9d4SSatish Balay } else { 7589d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7590d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7591d3d1a6afSToby Isaac newP++; 7592d3d1a6afSToby Isaac } 7593d3d1a6afSToby Isaac } 7594d3d1a6afSToby Isaac } else { 7595d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7596d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7597d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 75984b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7599d3d1a6afSToby Isaac 76009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7601ad540459SPierre Jolivet if (!bSecDof) continue; 760248a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7603d3d1a6afSToby Isaac if (bDof) { 7604d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7605d3d1a6afSToby Isaac 76069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76079566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7608d3d1a6afSToby Isaac 76099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7610d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7611d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7612d3d1a6afSToby Isaac 7613d3d1a6afSToby 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 */ 7614d3d1a6afSToby Isaac 7615d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7616d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 76179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 76189566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7619d3d1a6afSToby Isaac } 7620d3d1a6afSToby Isaac newP += bDof; 7621d3d1a6afSToby Isaac 7622d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 762348a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 76249371c9d4SSatish Balay } else { 7625d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7626d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7627d3d1a6afSToby Isaac newP++; 7628d3d1a6afSToby Isaac } 7629d3d1a6afSToby Isaac } 7630d3d1a6afSToby Isaac } 7631d3d1a6afSToby Isaac 76326ecaa68aSToby Isaac if (outValues) { 76339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 76349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7635d3d1a6afSToby Isaac /* multiply constraints on the right */ 7636d3d1a6afSToby Isaac if (numFields) { 7637d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7638d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7639d3d1a6afSToby Isaac 7640d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7641d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7642d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7643d3d1a6afSToby Isaac PetscInt c, r, k; 7644d3d1a6afSToby Isaac PetscInt dof; 7645d3d1a6afSToby Isaac 76469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7647ad540459SPierre Jolivet if (!dof) continue; 7648d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7649d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7650d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7651d3d1a6afSToby Isaac 7652d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7653d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7654ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7655d3d1a6afSToby Isaac } 7656d3d1a6afSToby Isaac } 76579371c9d4SSatish Balay } else { 7658d3d1a6afSToby Isaac /* copy this column as is */ 7659d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7660ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7661d3d1a6afSToby Isaac } 7662d3d1a6afSToby Isaac } 7663d3d1a6afSToby Isaac oldOff += dof; 7664d3d1a6afSToby Isaac } 7665d3d1a6afSToby Isaac } 76669371c9d4SSatish Balay } else { 7667d3d1a6afSToby Isaac PetscInt oldOff = 0; 7668d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7669d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7670d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7671d3d1a6afSToby Isaac PetscInt c, r, k; 7672d3d1a6afSToby Isaac PetscInt dof; 7673d3d1a6afSToby Isaac 76749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7675ad540459SPierre Jolivet if (!dof) continue; 7676d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7677d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7678d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7679d3d1a6afSToby Isaac 7680d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7681d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7682ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7683d3d1a6afSToby Isaac } 7684d3d1a6afSToby Isaac } 76859371c9d4SSatish Balay } else { 7686d3d1a6afSToby Isaac /* copy this column as is */ 7687d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7688ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7689d3d1a6afSToby Isaac } 7690d3d1a6afSToby Isaac } 7691d3d1a6afSToby Isaac oldOff += dof; 7692d3d1a6afSToby Isaac } 7693d3d1a6afSToby Isaac } 7694d3d1a6afSToby Isaac 76956ecaa68aSToby Isaac if (multiplyLeft) { 76969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 76979566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7698d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7699d3d1a6afSToby Isaac if (numFields) { 7700d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7701d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7702d3d1a6afSToby Isaac 7703d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7704d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7705d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7706d3d1a6afSToby Isaac PetscInt c, r, k; 7707d3d1a6afSToby Isaac PetscInt dof; 7708d3d1a6afSToby Isaac 77099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7710d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7711d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7712d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7713d3d1a6afSToby Isaac 7714d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7715d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7716ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7717d3d1a6afSToby Isaac } 7718d3d1a6afSToby Isaac } 77199371c9d4SSatish Balay } else { 7720d3d1a6afSToby Isaac /* copy this row as is */ 7721d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7722ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7723d3d1a6afSToby Isaac } 7724d3d1a6afSToby Isaac } 7725d3d1a6afSToby Isaac oldOff += dof; 7726d3d1a6afSToby Isaac } 7727d3d1a6afSToby Isaac } 77289371c9d4SSatish Balay } else { 7729d3d1a6afSToby Isaac PetscInt oldOff = 0; 7730d3d1a6afSToby Isaac 7731d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7732d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7733d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7734d3d1a6afSToby Isaac PetscInt c, r, k; 7735d3d1a6afSToby Isaac PetscInt dof; 7736d3d1a6afSToby Isaac 77379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7738d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7739d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7740d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7741d3d1a6afSToby Isaac 7742d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7743d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7744ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7745d3d1a6afSToby Isaac } 7746d3d1a6afSToby Isaac } 77479371c9d4SSatish Balay } else { 7748d3d1a6afSToby Isaac /* copy this row as is */ 77499fc93327SToby Isaac for (r = 0; r < dof; r++) { 7750ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7751d3d1a6afSToby Isaac } 7752d3d1a6afSToby Isaac } 7753d3d1a6afSToby Isaac oldOff += dof; 7754d3d1a6afSToby Isaac } 7755d3d1a6afSToby Isaac } 7756d3d1a6afSToby Isaac 77579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 77589371c9d4SSatish Balay } else { 77596ecaa68aSToby Isaac newValues = tmpValues; 77606ecaa68aSToby Isaac } 77616ecaa68aSToby Isaac } 77626ecaa68aSToby Isaac 7763d3d1a6afSToby Isaac /* clean up */ 77649566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 77659566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 77666ecaa68aSToby Isaac 7767d3d1a6afSToby Isaac if (numFields) { 7768d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 77699566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 77709566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 77719566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7772d3d1a6afSToby Isaac } 77739371c9d4SSatish Balay } else { 77749566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 77759566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 77769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7777d3d1a6afSToby Isaac } 77789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7779d3d1a6afSToby Isaac 7780d3d1a6afSToby Isaac /* output */ 77816ecaa68aSToby Isaac if (outPoints) { 7782d3d1a6afSToby Isaac *outPoints = newPoints; 77839371c9d4SSatish Balay } else { 77849566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 77856ecaa68aSToby Isaac } 7786ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7787ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 77883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7789d3d1a6afSToby Isaac } 7790d3d1a6afSToby Isaac 77914a1e0b3eSMatthew G. Knepley /*@C 779271f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 77937cd05799SMatthew G. Knepley 77947cd05799SMatthew G. Knepley Not collective 77957cd05799SMatthew G. Knepley 77967cd05799SMatthew G. Knepley Input Parameters: 7797a1cb98faSBarry Smith + dm - The `DM` 7798a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7799a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 780071f0bbf9SMatthew G. Knepley . point - The point defining the closure 780171f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 78027cd05799SMatthew G. Knepley 780371f0bbf9SMatthew G. Knepley Output Parameters: 780471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 780571f0bbf9SMatthew G. Knepley . indices - The dof indices 780620f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 780720f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 78087cd05799SMatthew G. Knepley 7809a1cb98faSBarry Smith Level: advanced 781036fa2b79SJed Brown 7811a1cb98faSBarry Smith Notes: 7812a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7813a1cb98faSBarry Smith 781420f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 781520f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 781636fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 781720f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 781836fa2b79SJed Brown indices (with the above semantics) are implied. 78197cd05799SMatthew G. Knepley 78201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7821a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 78224a1e0b3eSMatthew G. Knepley @*/ 7823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7824d71ae5a4SJacob Faibussowitsch { 782571f0bbf9SMatthew G. Knepley /* Closure ordering */ 78267773e69fSMatthew G. Knepley PetscSection clSection; 78277773e69fSMatthew G. Knepley IS clPoints; 782871f0bbf9SMatthew G. Knepley const PetscInt *clp; 782971f0bbf9SMatthew G. Knepley PetscInt *points; 783071f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 783171f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 78324acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 783371f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 783471f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 783571f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 783671f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 783771f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 783871f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 783971f0bbf9SMatthew G. Knepley 784071f0bbf9SMatthew G. Knepley PetscInt *idx; 784171f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 784271f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 78437773e69fSMatthew G. Knepley 784471f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 78457773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 78467773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 784736fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 78484f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 78494f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 78504f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 78514f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 78529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 785363a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 78549566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 785571f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 785607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7857c459fbc1SJed Brown if (useClPerm) { 7858c459fbc1SJed Brown PetscInt depth, clsize; 78599566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7860c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7861c459fbc1SJed Brown PetscInt dof; 78629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7863c459fbc1SJed Brown clsize += dof; 7864c459fbc1SJed Brown } 78659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7866c459fbc1SJed Brown } 786771f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 786871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 78697773e69fSMatthew G. Knepley PetscInt dof, fdof; 78707773e69fSMatthew G. Knepley 78719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 78727773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 78739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 78747773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 78757773e69fSMatthew G. Knepley } 787671f0bbf9SMatthew G. Knepley Ni += dof; 78777773e69fSMatthew G. Knepley } 78787773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 78791dca8a05SBarry 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); 788071f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 788171f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 78829566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 78839566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 788471f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 788571f0bbf9SMatthew G. Knepley if (values && flips[f]) { 788671f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 78876ecaa68aSToby Isaac 788871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 788971f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 789071f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 789171f0bbf9SMatthew G. Knepley 78929566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 78939566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 789471f0bbf9SMatthew G. Knepley if (flip) { 789571f0bbf9SMatthew G. Knepley PetscInt i, j, k; 789671f0bbf9SMatthew G. Knepley 789771f0bbf9SMatthew G. Knepley if (!valCopy) { 78989566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 789971f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 790071f0bbf9SMatthew G. Knepley *values = valCopy; 790171f0bbf9SMatthew G. Knepley } 790271f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 790371f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 790471f0bbf9SMatthew G. Knepley 790571f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 790671f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 790771f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 79086ecaa68aSToby Isaac } 79096ecaa68aSToby Isaac } 791071f0bbf9SMatthew G. Knepley } 791171f0bbf9SMatthew G. Knepley foffset += fdof; 791271f0bbf9SMatthew G. Knepley } 791371f0bbf9SMatthew G. Knepley } 791471f0bbf9SMatthew G. Knepley } 791571f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 79169566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 791771f0bbf9SMatthew G. Knepley if (NclC) { 79189566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 791971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79209566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79219566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 792271f0bbf9SMatthew G. Knepley } 792371f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79249566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 79259566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 792671f0bbf9SMatthew G. Knepley } 79279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 792871f0bbf9SMatthew G. Knepley Ncl = NclC; 792971f0bbf9SMatthew G. Knepley Ni = NiC; 793071f0bbf9SMatthew G. Knepley points = pointsC; 793171f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 793271f0bbf9SMatthew G. Knepley } 793371f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 79349566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 793571f0bbf9SMatthew G. Knepley if (Nf) { 793671f0bbf9SMatthew G. Knepley PetscInt idxOff; 793771f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 793871f0bbf9SMatthew G. Knepley 79399371c9d4SSatish Balay if (outOffsets) { 79409371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 79419371c9d4SSatish Balay } 79429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 794371f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 794471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 794571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 794671f0bbf9SMatthew G. Knepley 79479566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 79487773e69fSMatthew G. Knepley } 79497773e69fSMatthew G. Knepley } else { 795071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 795171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 795271f0bbf9SMatthew G. Knepley 79539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 795471f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 795571f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 795671f0bbf9SMatthew G. Knepley * global section. */ 79579566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 795871f0bbf9SMatthew G. Knepley } 795971f0bbf9SMatthew G. Knepley } 796071f0bbf9SMatthew G. Knepley } else { 796171f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 796271f0bbf9SMatthew G. Knepley 796371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 796471f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 79654acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 79664acb8e1eSToby Isaac 79679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 796871f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 796971f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 79709566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 79717773e69fSMatthew G. Knepley } 79727773e69fSMatthew G. Knepley } 797371f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 797471f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79759566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79769566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 79774acb8e1eSToby Isaac } 797871f0bbf9SMatthew G. Knepley if (NclC) { 79799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 79807773e69fSMatthew G. Knepley } else { 79819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 79827773e69fSMatthew G. Knepley } 798371f0bbf9SMatthew G. Knepley 798471f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 798571f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 79863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79877773e69fSMatthew G. Knepley } 79887773e69fSMatthew G. Knepley 79897cd05799SMatthew G. Knepley /*@C 799071f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 79917cd05799SMatthew G. Knepley 79927cd05799SMatthew G. Knepley Not collective 79937cd05799SMatthew G. Knepley 79947cd05799SMatthew G. Knepley Input Parameters: 7995a1cb98faSBarry Smith + dm - The `DM` 7996a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7997a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 799871f0bbf9SMatthew G. Knepley . point - The point defining the closure 799971f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 800071f0bbf9SMatthew G. Knepley 800171f0bbf9SMatthew G. Knepley Output Parameters: 800271f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 800371f0bbf9SMatthew G. Knepley . indices - The dof indices 800420f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 800520f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 800671f0bbf9SMatthew G. Knepley 8007a1cb98faSBarry Smith Level: advanced 800871f0bbf9SMatthew G. Knepley 8009a1cb98faSBarry Smith Notes: 8010a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8011a1cb98faSBarry Smith 8012a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 801371f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 801471f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 801571f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 801671f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 80177cd05799SMatthew G. Knepley 80181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 80197cd05799SMatthew G. Knepley @*/ 8020d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8021d71ae5a4SJacob Faibussowitsch { 80227773e69fSMatthew G. Knepley PetscFunctionBegin; 80237773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80244f572ea9SToby Isaac PetscAssertPointer(indices, 7); 80259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 80263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80277773e69fSMatthew G. Knepley } 80287773e69fSMatthew G. Knepley 8029e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8030d71ae5a4SJacob Faibussowitsch { 8031552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8032552f7358SJed Brown PetscInt *indices; 803371f0bbf9SMatthew G. Knepley PetscInt numIndices; 803471f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8035552f7358SJed Brown PetscErrorCode ierr; 8036552f7358SJed Brown 8037552f7358SJed Brown PetscFunctionBegin; 8038552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80399566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 80403dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 80419566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 80423dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8043e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8044552f7358SJed Brown 8045e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 80460d644c17SKarl Rupp 80479566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8048d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 80494a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8050552f7358SJed Brown if (ierr) { 8051552f7358SJed Brown PetscMPIInt rank; 8052552f7358SJed Brown 80539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 80549566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 80559566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 80569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 80579566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8058c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8059552f7358SJed Brown } 80604a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 80614a1e0b3eSMatthew G. Knepley PetscInt i; 80629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 806363a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 80649566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 80654a1e0b3eSMatthew G. Knepley } 806671f0bbf9SMatthew G. Knepley 80679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 80689566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 80693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80704acb8e1eSToby Isaac } 807171f0bbf9SMatthew G. Knepley 80724a1e0b3eSMatthew G. Knepley /*@C 8073e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8074e8e188d2SZach Atkins 8075e8e188d2SZach Atkins Not collective 8076e8e188d2SZach Atkins 8077e8e188d2SZach Atkins Input Parameters: 8078e8e188d2SZach Atkins + dm - The `DM` 8079e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8080e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8081e8e188d2SZach Atkins . A - The matrix 8082e8e188d2SZach Atkins . point - The point in the `DM` 8083e8e188d2SZach Atkins . values - The array of values 8084e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8085e8e188d2SZach Atkins 8086e8e188d2SZach Atkins Level: intermediate 8087e8e188d2SZach Atkins 8088e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8089e8e188d2SZach Atkins @*/ 8090e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8091e8e188d2SZach Atkins { 8092e8e188d2SZach Atkins PetscFunctionBegin; 8093e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8094e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8095e8e188d2SZach Atkins } 8096e8e188d2SZach Atkins 8097e8e188d2SZach Atkins /*@C 809860225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 80994a1e0b3eSMatthew G. Knepley 81004a1e0b3eSMatthew G. Knepley Not collective 81014a1e0b3eSMatthew G. Knepley 81024a1e0b3eSMatthew G. Knepley Input Parameters: 8103a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 810420f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8105e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 810620f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8107a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 810820f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8109e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 811020f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 81114a1e0b3eSMatthew G. Knepley . A - The matrix 8112a1cb98faSBarry Smith . point - The point in the `DM` 81134a1e0b3eSMatthew G. Knepley . values - The array of values 8114a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 81154a1e0b3eSMatthew G. Knepley 81164a1e0b3eSMatthew G. Knepley Level: intermediate 81174a1e0b3eSMatthew G. Knepley 81181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 81194a1e0b3eSMatthew G. Knepley @*/ 8120e8e188d2SZach 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) 8121d71ae5a4SJacob Faibussowitsch { 812271f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 812371f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 812471f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 812571f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 812671f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 812771f0bbf9SMatthew G. Knepley 812871f0bbf9SMatthew G. Knepley PetscFunctionBegin; 812971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 81309566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 813171f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 81329566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 813371f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8134e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 81359566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8136e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 81379566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8138e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8139e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 814071f0bbf9SMatthew G. Knepley 8141e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8142e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 814371f0bbf9SMatthew G. Knepley 81449566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 8145d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81464a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 814771f0bbf9SMatthew G. Knepley if (ierr) { 814871f0bbf9SMatthew G. Knepley PetscMPIInt rank; 814971f0bbf9SMatthew G. Knepley 81509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81519566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81529566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 81539566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 81549566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 81559566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 8156d3d1a6afSToby Isaac } 815771f0bbf9SMatthew G. Knepley 8158e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8159e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 81609566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 81613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8162552f7358SJed Brown } 8163552f7358SJed Brown 8164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8165d71ae5a4SJacob Faibussowitsch { 8166de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8167de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8168de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8169de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 817017c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8171de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8172412e9a14SMatthew G. Knepley DMPolytopeType ct; 81734ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8174de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8175de41b84cSMatthew G. Knepley 8176de41b84cSMatthew G. Knepley PetscFunctionBegin; 8177de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8178de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 81799566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8180de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 81819566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8182de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 81839566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8184de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 81859566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8186de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8187de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 81889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 818963a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 81909566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 81919566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8192de41b84cSMatthew G. Knepley /* Column indices */ 81939566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 81944ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8195de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8196de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 81979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8198de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8199de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8200de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8201de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8202de41b84cSMatthew G. Knepley ++q; 8203de41b84cSMatthew G. Knepley } 8204de41b84cSMatthew G. Knepley } 8205de41b84cSMatthew G. Knepley numCPoints = q; 8206de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8207de41b84cSMatthew G. Knepley PetscInt fdof; 8208de41b84cSMatthew G. Knepley 82099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 82104ca5e9f5SMatthew G. Knepley if (!dof) continue; 8211de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8213de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8214de41b84cSMatthew G. Knepley } 8215de41b84cSMatthew G. Knepley numCIndices += dof; 8216de41b84cSMatthew G. Knepley } 8217de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8218de41b84cSMatthew G. Knepley /* Row indices */ 82199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8220412e9a14SMatthew G. Knepley { 8221012bc364SMatthew G. Knepley DMPlexTransform tr; 8222012bc364SMatthew G. Knepley DMPolytopeType *rct; 8223012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8224012bc364SMatthew G. Knepley 82259566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 82269566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 82279566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8228012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 82299566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8230412e9a14SMatthew G. Knepley } 82319566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8232de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8233de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 82349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8235de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 82369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8237de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8238de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 82399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 82404ca5e9f5SMatthew G. Knepley if (!dof) continue; 82419371c9d4SSatish Balay for (s = 0; s < q; ++s) 82429371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 82434ca5e9f5SMatthew G. Knepley if (s < q) continue; 8244de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8245de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8246de41b84cSMatthew G. Knepley ++q; 8247de41b84cSMatthew G. Knepley } 8248de41b84cSMatthew G. Knepley } 82499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8250de41b84cSMatthew G. Knepley } 8251de41b84cSMatthew G. Knepley numFPoints = q; 8252de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8253de41b84cSMatthew G. Knepley PetscInt fdof; 8254de41b84cSMatthew G. Knepley 82559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 82564ca5e9f5SMatthew G. Knepley if (!dof) continue; 8257de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8259de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8260de41b84cSMatthew G. Knepley } 8261de41b84cSMatthew G. Knepley numFIndices += dof; 8262de41b84cSMatthew G. Knepley } 8263de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8264de41b84cSMatthew G. Knepley 82651dca8a05SBarry 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); 82661dca8a05SBarry 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); 82679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 82689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8269de41b84cSMatthew G. Knepley if (numFields) { 82704acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 82714acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 82724acb8e1eSToby Isaac 82734acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 82749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 82759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8276de41b84cSMatthew G. Knepley } 82774acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 82789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 82799566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 82804acb8e1eSToby Isaac } 82814acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 82829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 82839566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 82844acb8e1eSToby Isaac } 82854acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 82869566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 82879566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8288de41b84cSMatthew G. Knepley } 8289de41b84cSMatthew G. Knepley } else { 82904acb8e1eSToby Isaac const PetscInt **permsF = NULL; 82914acb8e1eSToby Isaac const PetscInt **permsC = NULL; 82924acb8e1eSToby Isaac 82939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 82949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 82954acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 82964acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 82974acb8e1eSToby Isaac 82989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 82999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8300de41b84cSMatthew G. Knepley } 83014acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 83024acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 83034acb8e1eSToby Isaac 83049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83059566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8306de41b84cSMatthew G. Knepley } 83079566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83089566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8309de41b84cSMatthew G. Knepley } 83109566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83114acb8e1eSToby Isaac /* TODO: flips */ 8312d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8313de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8314de41b84cSMatthew G. Knepley if (ierr) { 8315de41b84cSMatthew G. Knepley PetscMPIInt rank; 8316de41b84cSMatthew G. Knepley 83179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 83189566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 83199566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8322de41b84cSMatthew G. Knepley } 83239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 83249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 83273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8328de41b84cSMatthew G. Knepley } 8329de41b84cSMatthew G. Knepley 8330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8331d71ae5a4SJacob Faibussowitsch { 83327c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 83337c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 83347c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 833517c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8336412e9a14SMatthew G. Knepley DMPolytopeType ct; 83377c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 83387c927364SMatthew G. Knepley 83397c927364SMatthew G. Knepley PetscFunctionBegin; 83407c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 83417c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83429566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 83437c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 83449566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 83457c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 83469566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 83477c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 83489566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 83497c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 83509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 835163a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 83529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 83539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 83547c927364SMatthew G. Knepley /* Column indices */ 83559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83567c927364SMatthew G. Knepley maxFPoints = numCPoints; 83577c927364SMatthew G. Knepley /* Compress out points not in the section */ 83587c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 83599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 83607c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 83617c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 83627c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 83637c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 83647c927364SMatthew G. Knepley ++q; 83657c927364SMatthew G. Knepley } 83667c927364SMatthew G. Knepley } 83677c927364SMatthew G. Knepley numCPoints = q; 83687c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 83697c927364SMatthew G. Knepley PetscInt fdof; 83707c927364SMatthew G. Knepley 83719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 83727c927364SMatthew G. Knepley if (!dof) continue; 83737c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 83757c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 83767c927364SMatthew G. Knepley } 83777c927364SMatthew G. Knepley numCIndices += dof; 83787c927364SMatthew G. Knepley } 83797c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 83807c927364SMatthew G. Knepley /* Row indices */ 83819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8382412e9a14SMatthew G. Knepley { 8383012bc364SMatthew G. Knepley DMPlexTransform tr; 8384012bc364SMatthew G. Knepley DMPolytopeType *rct; 8385012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8386012bc364SMatthew G. Knepley 83879566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 83889566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 83899566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8390012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 83919566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8392412e9a14SMatthew G. Knepley } 83939566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 83947c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 83957c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 83969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 83977c927364SMatthew G. Knepley /* Compress out points not in the section */ 83989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 83997c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 84007c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 84019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 84027c927364SMatthew G. Knepley if (!dof) continue; 84039371c9d4SSatish Balay for (s = 0; s < q; ++s) 84049371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 84057c927364SMatthew G. Knepley if (s < q) continue; 84067c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 84077c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 84087c927364SMatthew G. Knepley ++q; 84097c927364SMatthew G. Knepley } 84107c927364SMatthew G. Knepley } 84119566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 84127c927364SMatthew G. Knepley } 84137c927364SMatthew G. Knepley numFPoints = q; 84147c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 84157c927364SMatthew G. Knepley PetscInt fdof; 84167c927364SMatthew G. Knepley 84179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 84187c927364SMatthew G. Knepley if (!dof) continue; 84197c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 84217c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 84227c927364SMatthew G. Knepley } 84237c927364SMatthew G. Knepley numFIndices += dof; 84247c927364SMatthew G. Knepley } 84257c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 84267c927364SMatthew G. Knepley 84271dca8a05SBarry 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); 84281dca8a05SBarry 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); 84297c927364SMatthew G. Knepley if (numFields) { 84304acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84314acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84324acb8e1eSToby Isaac 84334acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 84367c927364SMatthew G. Knepley } 84374acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84399566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84404acb8e1eSToby Isaac } 84414acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84444acb8e1eSToby Isaac } 84454acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84469566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84479566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 84487c927364SMatthew G. Knepley } 84497c927364SMatthew G. Knepley } else { 84504acb8e1eSToby Isaac const PetscInt **permsF = NULL; 84514acb8e1eSToby Isaac const PetscInt **permsC = NULL; 84524acb8e1eSToby Isaac 84539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84554acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 84564acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 84574acb8e1eSToby Isaac 84589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84599566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 84607c927364SMatthew G. Knepley } 84614acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 84624acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 84634acb8e1eSToby Isaac 84649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84659566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 84667c927364SMatthew G. Knepley } 84679566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84689566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84697c927364SMatthew G. Knepley } 84709566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 84719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 84737c927364SMatthew G. Knepley } 84747c927364SMatthew G. Knepley 84757cd05799SMatthew G. Knepley /*@C 84767cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 84777cd05799SMatthew G. Knepley 84787cd05799SMatthew G. Knepley Input Parameter: 8479a1cb98faSBarry Smith . dm - The `DMPLEX` object 84807cd05799SMatthew G. Knepley 84817cd05799SMatthew G. Knepley Output Parameter: 84827cd05799SMatthew G. Knepley . cellHeight - The height of a cell 84837cd05799SMatthew G. Knepley 84847cd05799SMatthew G. Knepley Level: developer 84857cd05799SMatthew G. Knepley 84861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 84877cd05799SMatthew G. Knepley @*/ 8488d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8489d71ae5a4SJacob Faibussowitsch { 8490552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8491552f7358SJed Brown 8492552f7358SJed Brown PetscFunctionBegin; 8493552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 84944f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8495552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 84963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8497552f7358SJed Brown } 8498552f7358SJed Brown 84997cd05799SMatthew G. Knepley /*@C 85007cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 85017cd05799SMatthew G. Knepley 85027cd05799SMatthew G. Knepley Input Parameters: 8503a1cb98faSBarry Smith + dm - The `DMPLEX` object 85047cd05799SMatthew G. Knepley - cellHeight - The height of a cell 85057cd05799SMatthew G. Knepley 85067cd05799SMatthew G. Knepley Level: developer 85077cd05799SMatthew G. Knepley 85081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 85097cd05799SMatthew G. Knepley @*/ 8510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8511d71ae5a4SJacob Faibussowitsch { 8512552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8513552f7358SJed Brown 8514552f7358SJed Brown PetscFunctionBegin; 8515552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8516552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 85173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8518552f7358SJed Brown } 8519552f7358SJed Brown 8520e6139122SMatthew G. Knepley /*@ 85212827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8522e6139122SMatthew G. Knepley 85232827ebadSStefano Zampini Input Parameters: 85242827ebadSStefano Zampini + dm - The `DMPLEX` object 85252827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8526e6139122SMatthew G. Knepley 8527e6139122SMatthew G. Knepley Output Parameters: 85282827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 85292827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8530e6139122SMatthew G. Knepley 85312a9f31c0SMatthew G. Knepley Level: advanced 8532e6139122SMatthew G. Knepley 85332827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8534e6139122SMatthew G. Knepley @*/ 85352827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8536d71ae5a4SJacob Faibussowitsch { 85372827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 85382827ebadSStefano Zampini DMLabel label; 85392827ebadSStefano Zampini PetscInt pStart, pEnd; 8540e6139122SMatthew G. Knepley 8541e6139122SMatthew G. Knepley PetscFunctionBegin; 8542e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85432827ebadSStefano Zampini if (start) { 85444f572ea9SToby Isaac PetscAssertPointer(start, 3); 85452827ebadSStefano Zampini *start = 0; 85462827ebadSStefano Zampini } 85472827ebadSStefano Zampini if (end) { 85484f572ea9SToby Isaac PetscAssertPointer(end, 4); 85492827ebadSStefano Zampini *end = 0; 85502827ebadSStefano Zampini } 85512827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 85522827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 85532827ebadSStefano Zampini if (mesh->tr) { 85542827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 85552827ebadSStefano Zampini } else { 85562827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 85572827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 85582827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 85592827ebadSStefano Zampini } 85603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8561e6139122SMatthew G. Knepley } 8562e6139122SMatthew G. Knepley 8563d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8564d71ae5a4SJacob Faibussowitsch { 8565552f7358SJed Brown PetscSection section, globalSection; 8566552f7358SJed Brown PetscInt *numbers, p; 8567552f7358SJed Brown 8568552f7358SJed Brown PetscFunctionBegin; 8569d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 85709566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 85719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 857248a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 85739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 85749566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 85759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8576552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 85779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8578ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8579ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8580552f7358SJed Brown } 85819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8582ef48cebcSMatthew G. Knepley if (globalSize) { 8583ef48cebcSMatthew G. Knepley PetscLayout layout; 85849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 85859566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 85869566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8587ef48cebcSMatthew G. Knepley } 85889566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 85899566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 85903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8591552f7358SJed Brown } 8592552f7358SJed Brown 8593d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8594d71ae5a4SJacob Faibussowitsch { 8595412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8596552f7358SJed Brown 8597552f7358SJed Brown PetscFunctionBegin; 85989566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 85999566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 86009566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 86019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 86023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8603552f7358SJed Brown } 860481ed3555SMatthew G. Knepley 86058dab3259SMatthew G. Knepley /*@ 86067cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 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 . globalCellNumbers - Global cell numbers for all cells on this process 86137cd05799SMatthew G. Knepley 86147cd05799SMatthew G. Knepley Level: developer 86157cd05799SMatthew G. Knepley 86161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 86177cd05799SMatthew G. Knepley @*/ 8618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8619d71ae5a4SJacob Faibussowitsch { 862081ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 862181ed3555SMatthew G. Knepley 862281ed3555SMatthew G. Knepley PetscFunctionBegin; 862381ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86249566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8625552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 86263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8627552f7358SJed Brown } 8628552f7358SJed Brown 8629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8630d71ae5a4SJacob Faibussowitsch { 8631412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 863281ed3555SMatthew G. Knepley 863381ed3555SMatthew G. Knepley PetscFunctionBegin; 863481ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 86369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 86373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 863881ed3555SMatthew G. Knepley } 863981ed3555SMatthew G. Knepley 86408dab3259SMatthew G. Knepley /*@ 86416aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 86427cd05799SMatthew G. Knepley 86437cd05799SMatthew G. Knepley Input Parameter: 8644a1cb98faSBarry Smith . dm - The `DMPLEX` object 86457cd05799SMatthew G. Knepley 86467cd05799SMatthew G. Knepley Output Parameter: 86477cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 86487cd05799SMatthew G. Knepley 86497cd05799SMatthew G. Knepley Level: developer 86507cd05799SMatthew G. Knepley 86511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 86527cd05799SMatthew G. Knepley @*/ 8653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8654d71ae5a4SJacob Faibussowitsch { 8655552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8656552f7358SJed Brown 8657552f7358SJed Brown PetscFunctionBegin; 8658552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86599566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8660552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 86613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8662552f7358SJed Brown } 8663552f7358SJed Brown 86648dab3259SMatthew G. Knepley /*@ 8665966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8666966484cfSJed Brown 866720f4b53cSBarry Smith Collective 86687cd05799SMatthew G. Knepley 86697cd05799SMatthew G. Knepley Input Parameter: 8670a1cb98faSBarry Smith . dm - The `DMPLEX` object 86717cd05799SMatthew G. Knepley 86727cd05799SMatthew G. Knepley Output Parameter: 86737cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 86747cd05799SMatthew G. Knepley 8675a1cb98faSBarry Smith Level: developer 8676966484cfSJed Brown 8677a1cb98faSBarry Smith Notes: 8678a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8679966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8680966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8681966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8682966484cfSJed Brown 8683966484cfSJed Brown The partitioned mesh is 8684966484cfSJed Brown ``` 8685966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8686966484cfSJed Brown ``` 8687966484cfSJed Brown and its global numbering is 8688966484cfSJed Brown ``` 8689966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8690966484cfSJed Brown ``` 8691966484cfSJed Brown Then the global numbering is provided as 8692966484cfSJed Brown ``` 8693966484cfSJed Brown [0] Number of indices in set 5 8694966484cfSJed Brown [0] 0 0 8695966484cfSJed Brown [0] 1 1 8696966484cfSJed Brown [0] 2 3 8697966484cfSJed Brown [0] 3 4 8698966484cfSJed Brown [0] 4 -6 8699966484cfSJed Brown [1] Number of indices in set 3 8700966484cfSJed Brown [1] 0 2 8701966484cfSJed Brown [1] 1 5 8702966484cfSJed Brown [1] 2 6 8703966484cfSJed Brown ``` 8704966484cfSJed Brown 87051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87067cd05799SMatthew G. Knepley @*/ 8707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8708d71ae5a4SJacob Faibussowitsch { 8709ef48cebcSMatthew G. Knepley IS nums[4]; 8710862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8711ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 87120c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8713ef48cebcSMatthew G. Knepley 8714ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8715ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 87170c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 87189566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 87190c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8720862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8721862913ffSStefano Zampini PetscInt end; 8722862913ffSStefano Zampini 8723862913ffSStefano Zampini depths[d] = depth - d; 87249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 87250c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8726862913ffSStefano Zampini } 87270c15888dSMatthew G. Knepley if (empty) 87280c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 87290c15888dSMatthew G. Knepley depths[d] = -1; 87300c15888dSMatthew G. Knepley starts[d] = -1; 87310c15888dSMatthew G. Knepley } 87320c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 87331c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8734ad540459SPierre 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]); 87350c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8736ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8737ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8738ef48cebcSMatthew G. Knepley 87399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 87409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8741ef48cebcSMatthew G. Knepley shift += gsize; 8742ef48cebcSMatthew G. Knepley } 8743d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 87449566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 87453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8746ef48cebcSMatthew G. Knepley } 8747ef48cebcSMatthew G. Knepley 874808a22f4bSMatthew G. Knepley /*@ 874908a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 875008a22f4bSMatthew G. Knepley 875108a22f4bSMatthew G. Knepley Input Parameter: 8752a1cb98faSBarry Smith . dm - The `DMPLEX` object 875308a22f4bSMatthew G. Knepley 875408a22f4bSMatthew G. Knepley Output Parameter: 875508a22f4bSMatthew G. Knepley . ranks - The rank field 875608a22f4bSMatthew G. Knepley 8757a1cb98faSBarry Smith Options Database Key: 875820f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 875908a22f4bSMatthew G. Knepley 876008a22f4bSMatthew G. Knepley Level: intermediate 876108a22f4bSMatthew G. Knepley 87621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 876308a22f4bSMatthew G. Knepley @*/ 8764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8765d71ae5a4SJacob Faibussowitsch { 876608a22f4bSMatthew G. Knepley DM rdm; 876708a22f4bSMatthew G. Knepley PetscFE fe; 876808a22f4bSMatthew G. Knepley PetscScalar *r; 876908a22f4bSMatthew G. Knepley PetscMPIInt rank; 8770a55f9a55SMatthew G. Knepley DMPolytopeType ct; 877108a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8772a55f9a55SMatthew G. Knepley PetscBool simplex; 877308a22f4bSMatthew G. Knepley 877408a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8775f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87764f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 87779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 87789566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 87799566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 87809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 87819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8782a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 87839566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 87849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 87859566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 87869566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 87879566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 87889566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 87899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 87909566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 879108a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 879208a22f4bSMatthew G. Knepley PetscScalar *lr; 879308a22f4bSMatthew G. Knepley 87949566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 879571f09efeSPierre Jolivet if (lr) *lr = rank; 879608a22f4bSMatthew G. Knepley } 87979566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 87989566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 87993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 880008a22f4bSMatthew G. Knepley } 880108a22f4bSMatthew G. Knepley 8802ca8062c8SMatthew G. Knepley /*@ 880318e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 880418e14f0cSMatthew G. Knepley 880518e14f0cSMatthew G. Knepley Input Parameters: 880620f4b53cSBarry Smith + dm - The `DMPLEX` 880720f4b53cSBarry Smith - label - The `DMLabel` 880818e14f0cSMatthew G. Knepley 880918e14f0cSMatthew G. Knepley Output Parameter: 881018e14f0cSMatthew G. Knepley . val - The label value field 881118e14f0cSMatthew G. Knepley 881220f4b53cSBarry Smith Options Database Key: 881320f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 881418e14f0cSMatthew G. Knepley 881518e14f0cSMatthew G. Knepley Level: intermediate 881618e14f0cSMatthew G. Knepley 88171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 881818e14f0cSMatthew G. Knepley @*/ 8819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8820d71ae5a4SJacob Faibussowitsch { 882118e14f0cSMatthew G. Knepley DM rdm; 882218e14f0cSMatthew G. Knepley PetscFE fe; 882318e14f0cSMatthew G. Knepley PetscScalar *v; 882418e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 882518e14f0cSMatthew G. Knepley 882618e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 882718e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88284f572ea9SToby Isaac PetscAssertPointer(label, 2); 88294f572ea9SToby Isaac PetscAssertPointer(val, 3); 88309566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 88319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 88329566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 88339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 88349566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 88359566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 88369566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 88379566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 88389566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 88399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 88409566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 884118e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 884218e14f0cSMatthew G. Knepley PetscScalar *lv; 884318e14f0cSMatthew G. Knepley PetscInt cval; 884418e14f0cSMatthew G. Knepley 88459566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 88469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 884718e14f0cSMatthew G. Knepley *lv = cval; 884818e14f0cSMatthew G. Knepley } 88499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 88509566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 88513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885218e14f0cSMatthew G. Knepley } 885318e14f0cSMatthew G. Knepley 885418e14f0cSMatthew G. Knepley /*@ 8855ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8856ca8062c8SMatthew G. Knepley 885769916449SMatthew G. Knepley Input Parameter: 8858a1cb98faSBarry Smith . dm - The `DMPLEX` object 8859a1cb98faSBarry Smith 8860a1cb98faSBarry Smith Level: developer 8861ca8062c8SMatthew G. Knepley 886295eb5ee5SVaclav Hapla Notes: 886395eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 886495eb5ee5SVaclav Hapla 886520f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8866ca8062c8SMatthew G. Knepley 88671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8868ca8062c8SMatthew G. Knepley @*/ 8869d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8870d71ae5a4SJacob Faibussowitsch { 8871ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8872ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8873ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 887457beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 887557beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8876ca8062c8SMatthew G. Knepley 8877ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8878ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88799566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 88809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 88819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8882ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 88839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8884ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 88859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 88869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8887ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 888842e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 888942e66dfaSMatthew G. Knepley PetscInt d; 889042e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 88919371c9d4SSatish Balay if (cone[c] == cone[d]) { 88929371c9d4SSatish Balay dup = PETSC_TRUE; 88939371c9d4SSatish Balay break; 88949371c9d4SSatish Balay } 889542e66dfaSMatthew G. Knepley } 88969566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 88979566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8898ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8899ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8900ca8062c8SMatthew G. Knepley } 890142e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 890263a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 890348a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 89049566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 890563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 890648a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 89079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 890863a3b9bcSJacob 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]); 8909f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8910ca8062c8SMatthew G. Knepley } 891142e66dfaSMatthew G. Knepley } 89129566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 89139371c9d4SSatish Balay if (p != pp) { 89149371c9d4SSatish Balay storagecheck = PETSC_FALSE; 89159371c9d4SSatish Balay continue; 89169371c9d4SSatish Balay } 89179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 89189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8919ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 89209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 89219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8922ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 89239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 89249371c9d4SSatish Balay if (cone[c] != pp) { 89259371c9d4SSatish Balay c = 0; 89269371c9d4SSatish Balay break; 89279371c9d4SSatish Balay } 8928ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8929ca8062c8SMatthew G. Knepley } 8930ca8062c8SMatthew G. Knepley if (c >= coneSize) { 893163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 893248a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 89339566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 893463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 893548a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 89369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 893763a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8938ca8062c8SMatthew G. Knepley } 8939ca8062c8SMatthew G. Knepley } 8940ca8062c8SMatthew G. Knepley } 894157beb4faSStefano Zampini if (storagecheck) { 89429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 89439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 894463a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 894557beb4faSStefano Zampini } 89463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8947ca8062c8SMatthew G. Knepley } 8948ca8062c8SMatthew G. Knepley 8949412e9a14SMatthew G. Knepley /* 8950412e9a14SMatthew 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. 8951412e9a14SMatthew G. Knepley */ 8952d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 8953d71ae5a4SJacob Faibussowitsch { 8954412e9a14SMatthew G. Knepley DMPolytopeType cct; 8955412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 8956412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 8957412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 8958412e9a14SMatthew G. Knepley 8959412e9a14SMatthew G. Knepley PetscFunctionBegin; 8960412e9a14SMatthew G. Knepley *unsplit = 0; 8961412e9a14SMatthew G. Knepley switch (ct) { 8962d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 8963d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 8964d71ae5a4SJacob Faibussowitsch break; 8965412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 89669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 89679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8968412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 89699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 8970412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 8971412e9a14SMatthew G. Knepley } 8972412e9a14SMatthew G. Knepley break; 8973412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 8974412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 89759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 89769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 8977412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 89789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 89799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 8980412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 89819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 8982412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 8983412e9a14SMatthew G. Knepley PetscInt p; 89849371c9d4SSatish Balay for (p = 0; p < npt; ++p) 89859371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 8986412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 8987412e9a14SMatthew G. Knepley } 8988412e9a14SMatthew G. Knepley } 8989412e9a14SMatthew G. Knepley } 8990412e9a14SMatthew G. Knepley break; 8991d71ae5a4SJacob Faibussowitsch default: 8992d71ae5a4SJacob Faibussowitsch break; 8993412e9a14SMatthew G. Knepley } 8994412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 89959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 8996412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 8997412e9a14SMatthew G. Knepley } 89983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8999412e9a14SMatthew G. Knepley } 9000412e9a14SMatthew G. Knepley 9001ca8062c8SMatthew G. Knepley /*@ 9002ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9003ca8062c8SMatthew G. Knepley 9004ca8062c8SMatthew G. Knepley Input Parameters: 9005a1cb98faSBarry Smith + dm - The `DMPLEX` object 900658723a97SMatthew G. Knepley - cellHeight - Normally 0 9007ca8062c8SMatthew G. Knepley 9008a1cb98faSBarry Smith Level: developer 9009a1cb98faSBarry Smith 901095eb5ee5SVaclav Hapla Notes: 901195eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 901225c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9013ca8062c8SMatthew G. Knepley 901420f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 901595eb5ee5SVaclav Hapla 90161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9017ca8062c8SMatthew G. Knepley @*/ 9018d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9019d71ae5a4SJacob Faibussowitsch { 9020412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9021412e9a14SMatthew G. Knepley DMPolytopeType ct; 9022412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9023ca8062c8SMatthew G. Knepley 9024ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9025ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90269566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 90279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9029412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9030412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9031412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 903258723a97SMatthew G. Knepley 90339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 903463a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9035412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9036412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 90379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 903863a3b9bcSJacob 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)); 9039412e9a14SMatthew G. Knepley } 90409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 904158723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 904258723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9043412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 904458723a97SMatthew G. Knepley } 90459566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9046412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9047412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9048412e9a14SMatthew G. Knepley PetscInt unsplit; 904942363296SMatthew G. Knepley 90509566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9051412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 905242363296SMatthew G. Knepley } 905363a3b9bcSJacob 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)); 905442363296SMatthew G. Knepley } 90553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9056ca8062c8SMatthew G. Knepley } 90579bf0dad6SMatthew G. Knepley 90589bf0dad6SMatthew G. Knepley /*@ 90599bf0dad6SMatthew 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 90609bf0dad6SMatthew G. Knepley 906120f4b53cSBarry Smith Collective 9062899ea2b8SJacob Faibussowitsch 90639bf0dad6SMatthew G. Knepley Input Parameters: 9064a1cb98faSBarry Smith + dm - The `DMPLEX` object 90659bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 90669bf0dad6SMatthew G. Knepley 9067a1cb98faSBarry Smith Level: developer 9068a1cb98faSBarry Smith 906945da879fSVaclav Hapla Notes: 907045da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 907145da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 907245da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 907345da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 90749bf0dad6SMatthew G. Knepley 9075a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 907695eb5ee5SVaclav Hapla 90771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 90789bf0dad6SMatthew G. Knepley @*/ 9079d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9080d71ae5a4SJacob Faibussowitsch { 9081ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9082899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 90839bf0dad6SMatthew G. Knepley 90849bf0dad6SMatthew G. Knepley PetscFunctionBegin; 90859bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90868f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 90873ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 90888f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 90893ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 90903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9091899ea2b8SJacob Faibussowitsch } 9092899ea2b8SJacob Faibussowitsch 90939566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 90949566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 90959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9096ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 90979566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 90983554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9099412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9100412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9101ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9102412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9103412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 91049bf0dad6SMatthew G. Knepley 91059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 91069566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9107412e9a14SMatthew G. Knepley if (unsplit) continue; 91089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 91099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 91119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 91129bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 91139bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 91149bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 91159bf0dad6SMatthew G. Knepley } 91169566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 911763a3b9bcSJacob 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); 91189bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9119d4961f80SStefano Zampini DMPolytopeType fct; 91209bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 91219bf0dad6SMatthew G. Knepley 91229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 91239566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 91249bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 91259bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 91269bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 91279bf0dad6SMatthew G. Knepley } 912863a3b9bcSJacob 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]); 91299bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9130b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9131b5a892a1SMatthew G. Knepley PetscInt v1; 9132b5a892a1SMatthew G. Knepley 91339566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 913463a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 91359566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 913663a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 91379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 913863a3b9bcSJacob 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]); 9139b5a892a1SMatthew G. Knepley } 91409bf0dad6SMatthew G. Knepley } 91419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9142412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 91439bf0dad6SMatthew G. Knepley } 91449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 91459566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 91469bf0dad6SMatthew G. Knepley } 91473554e41dSMatthew G. Knepley } 91483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9149552f7358SJed Brown } 91503913d7c8SMatthew G. Knepley 9151bb6a34a8SMatthew G. Knepley /*@ 9152bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9153bb6a34a8SMatthew G. Knepley 9154bb6a34a8SMatthew G. Knepley Input Parameter: 9155a1cb98faSBarry Smith . dm - The `DMPLEX` object 9156a1cb98faSBarry Smith 9157a1cb98faSBarry Smith Level: developer 9158bb6a34a8SMatthew G. Knepley 915995eb5ee5SVaclav Hapla Notes: 916095eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 916195eb5ee5SVaclav Hapla 916220f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9163bb6a34a8SMatthew G. Knepley 91641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9165bb6a34a8SMatthew G. Knepley @*/ 9166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9167d71ae5a4SJacob Faibussowitsch { 9168a2a9e04cSMatthew G. Knepley Vec coordinates; 9169bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9170bb6a34a8SMatthew G. Knepley PetscReal vol; 917151a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9172bb6a34a8SMatthew G. Knepley 9173bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 91749566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 91759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 91763ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 91779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9178bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 91799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9180a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 91819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 91823ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9183412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9184412e9a14SMatthew G. Knepley DMPolytopeType ct; 9185412e9a14SMatthew G. Knepley PetscInt unsplit; 9186412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9187412e9a14SMatthew G. Knepley 91889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9189412e9a14SMatthew G. Knepley switch (ct) { 9190412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9191412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9192d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9193d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9194d71ae5a4SJacob Faibussowitsch break; 9195d71ae5a4SJacob Faibussowitsch default: 9196d71ae5a4SJacob Faibussowitsch break; 9197412e9a14SMatthew G. Knepley } 9198412e9a14SMatthew G. Knepley switch (ct) { 9199412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9200412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9201412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9202d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9203d71ae5a4SJacob Faibussowitsch continue; 9204d71ae5a4SJacob Faibussowitsch default: 9205d71ae5a4SJacob Faibussowitsch break; 9206412e9a14SMatthew G. Knepley } 92079566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9208412e9a14SMatthew G. Knepley if (unsplit) continue; 92099566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 92101dca8a05SBarry 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); 921163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 92126858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 92136858538eSMatthew G. Knepley if (depth > 1) { 92149566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 92151dca8a05SBarry 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); 921663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9217bb6a34a8SMatthew G. Knepley } 9218bb6a34a8SMatthew G. Knepley } 92193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9220bb6a34a8SMatthew G. Knepley } 9221bb6a34a8SMatthew G. Knepley 922203da9461SVaclav Hapla /*@ 922320f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 92247726db96SVaclav Hapla 922520f4b53cSBarry Smith Collective 922603da9461SVaclav Hapla 922703da9461SVaclav Hapla Input Parameters: 9228a1cb98faSBarry Smith + dm - The `DMPLEX` object 922920f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9230a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9231a1cb98faSBarry Smith 9232a1cb98faSBarry Smith Level: developer 923303da9461SVaclav Hapla 9234e83a0d2dSVaclav Hapla Notes: 9235e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 923603da9461SVaclav Hapla 9237a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 923895eb5ee5SVaclav Hapla 9239baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9240d7d32a9aSMatthew G. Knepley 92411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 924203da9461SVaclav Hapla @*/ 9243d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9244d71ae5a4SJacob Faibussowitsch { 92457726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 92467726db96SVaclav Hapla const PetscInt *locals; 92477726db96SVaclav Hapla const PetscSFNode *remotes; 9248f0cfc026SVaclav Hapla PetscBool distributed; 92497726db96SVaclav Hapla MPI_Comm comm; 92507726db96SVaclav Hapla PetscMPIInt rank; 925103da9461SVaclav Hapla 925203da9461SVaclav Hapla PetscFunctionBegin; 925303da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92547726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 92557726db96SVaclav Hapla else pointSF = dm->sf; 92567726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 92577726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 92587726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 92597726db96SVaclav Hapla { 92607726db96SVaclav Hapla PetscMPIInt mpiFlag; 92617726db96SVaclav Hapla 92627726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 92637726db96SVaclav 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); 92647726db96SVaclav Hapla } 92657726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 92669566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 92677726db96SVaclav Hapla if (!distributed) { 92687726db96SVaclav 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); 92693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92708918e3e2SVaclav Hapla } 92717726db96SVaclav 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); 92727726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 927303da9461SVaclav Hapla 92747726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 92757726db96SVaclav Hapla { 92767726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 92777726db96SVaclav Hapla 92787726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 92797726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9280d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 92817726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 92827726db96SVaclav Hapla } 92837726db96SVaclav Hapla 92847726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 92857726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 92867726db96SVaclav 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); 92877726db96SVaclav Hapla } 92887726db96SVaclav Hapla 92897726db96SVaclav Hapla /* Check there are no cells in interface */ 92907726db96SVaclav Hapla if (!overlap) { 92917726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 92927726db96SVaclav Hapla 92939566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 92949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9295f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 92967726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9297f5869d18SMatthew G. Knepley 92987726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 92997726db96SVaclav Hapla } 930003da9461SVaclav Hapla } 9301ece87651SVaclav Hapla 93027726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 93037726db96SVaclav Hapla { 93047726db96SVaclav Hapla const PetscInt *rootdegree; 93057726db96SVaclav Hapla 93067726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 93077726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9308f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93097726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9310f5869d18SMatthew G. Knepley const PetscInt *cone; 9311f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9312f5869d18SMatthew G. Knepley 93139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 93149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9315f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9316f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 93177726db96SVaclav Hapla if (locals) { 93189566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 93197726db96SVaclav Hapla } else { 93207726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 93217726db96SVaclav Hapla } 932263a3b9bcSJacob 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]); 9323f5869d18SMatthew G. Knepley } 9324f5869d18SMatthew G. Knepley } 9325ece87651SVaclav Hapla } 93267726db96SVaclav Hapla } 93273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 932803da9461SVaclav Hapla } 932903da9461SVaclav Hapla 93307f9d8d6cSVaclav Hapla /*@ 933120f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 93327f9d8d6cSVaclav Hapla 93337f9d8d6cSVaclav Hapla Input Parameter: 9334a1cb98faSBarry Smith . dm - The `DMPLEX` object 9335a1cb98faSBarry Smith 9336a1cb98faSBarry Smith Level: developer 93377f9d8d6cSVaclav Hapla 93387f9d8d6cSVaclav Hapla Notes: 93397f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 93407f9d8d6cSVaclav Hapla 934120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 93427f9d8d6cSVaclav Hapla 934320f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 93447f9d8d6cSVaclav Hapla 93451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 93467f9d8d6cSVaclav Hapla @*/ 9347d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9348d71ae5a4SJacob Faibussowitsch { 93497f9d8d6cSVaclav Hapla PetscInt cellHeight; 93507f9d8d6cSVaclav Hapla 9351b5a892a1SMatthew G. Knepley PetscFunctionBegin; 93527f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 93539566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 93549566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 93559566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 93569566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9357d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 93589566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 93593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9360b5a892a1SMatthew G. Knepley } 9361b5a892a1SMatthew G. Knepley 93629371c9d4SSatish Balay typedef struct cell_stats { 9363068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9364068a5610SStefano Zampini PetscInt count; 9365068a5610SStefano Zampini } cell_stats_t; 9366068a5610SStefano Zampini 9367d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9368d71ae5a4SJacob Faibussowitsch { 9369068a5610SStefano Zampini PetscInt i, N = *len; 9370068a5610SStefano Zampini 9371068a5610SStefano Zampini for (i = 0; i < N; i++) { 9372068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9373068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9374068a5610SStefano Zampini 9375068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9376068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9377068a5610SStefano Zampini B->sum += A->sum; 9378068a5610SStefano Zampini B->squaresum += A->squaresum; 9379068a5610SStefano Zampini B->count += A->count; 9380068a5610SStefano Zampini } 9381068a5610SStefano Zampini } 9382068a5610SStefano Zampini 9383068a5610SStefano Zampini /*@ 938443fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9385068a5610SStefano Zampini 938620f4b53cSBarry Smith Collective 93878261a58bSMatthew G. Knepley 9388068a5610SStefano Zampini Input Parameters: 9389a1cb98faSBarry Smith + dm - The `DMPLEX` object 939020f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9391a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9392a1cb98faSBarry Smith 9393a1cb98faSBarry Smith Level: developer 9394068a5610SStefano Zampini 939595eb5ee5SVaclav Hapla Notes: 939695eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 939795eb5ee5SVaclav Hapla 9398a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9399068a5610SStefano Zampini 94001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9401068a5610SStefano Zampini @*/ 9402d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9403d71ae5a4SJacob Faibussowitsch { 9404068a5610SStefano Zampini DM dmCoarse; 940543fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 940643fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 940743fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 940843fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9409412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 941043fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9411068a5610SStefano Zampini 9412068a5610SStefano Zampini PetscFunctionBegin; 9413068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9414068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9415068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9416068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9417068a5610SStefano Zampini stats.count = 0; 9418068a5610SStefano Zampini 94199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 94209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 94229566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 94239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 94249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9425412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9426068a5610SStefano Zampini PetscInt i; 9427068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9428068a5610SStefano Zampini 94299566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 943063a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 943143fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9432068a5610SStefano Zampini frobJ += J[i] * J[i]; 9433068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9434068a5610SStefano Zampini } 9435068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9436068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9437068a5610SStefano Zampini 9438068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9439068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9440068a5610SStefano Zampini stats.sum += cond; 9441068a5610SStefano Zampini stats.squaresum += cond2; 9442068a5610SStefano Zampini stats.count++; 94438261a58bSMatthew G. Knepley if (output && cond > limit) { 944443fa8764SMatthew G. Knepley PetscSection coordSection; 944543fa8764SMatthew G. Knepley Vec coordsLocal; 944643fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 944743fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 944843fa8764SMatthew G. Knepley 94499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 94509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 94519566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 945263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 945343fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 945463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 945543fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 94569566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 94579566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 945843fa8764SMatthew G. Knepley } 94599566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 946043fa8764SMatthew G. Knepley } 94619566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 946243fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 946343fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 946443fa8764SMatthew G. Knepley 946543fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 946643fa8764SMatthew G. Knepley PetscReal len; 946743fa8764SMatthew G. Knepley 94689566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 946963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 947043fa8764SMatthew G. Knepley } 947143fa8764SMatthew G. Knepley } 94729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 94739566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 947443fa8764SMatthew G. Knepley } 9475068a5610SStefano Zampini } 94769566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9477068a5610SStefano Zampini 9478068a5610SStefano Zampini if (size > 1) { 9479068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9480068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9481068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9482068a5610SStefano Zampini MPI_Op statReduce; 9483068a5610SStefano Zampini 94849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 94859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 94869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 94879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 94889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 94899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9490068a5610SStefano Zampini } else { 94919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9492068a5610SStefano Zampini } 9493dd400576SPatrick Sanan if (rank == 0) { 9494068a5610SStefano Zampini count = globalStats.count; 9495068a5610SStefano Zampini min = globalStats.min; 9496068a5610SStefano Zampini max = globalStats.max; 9497068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9498068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9499068a5610SStefano Zampini } 9500068a5610SStefano Zampini 950148a46eb9SPierre 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)); 95029566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9503068a5610SStefano Zampini 95049566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9505068a5610SStefano Zampini if (dmCoarse) { 9506068a5610SStefano Zampini PetscBool isplex; 9507068a5610SStefano Zampini 95089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 95091baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9510068a5610SStefano Zampini } 95113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9512068a5610SStefano Zampini } 9513068a5610SStefano Zampini 9514f108dbd7SJacob Faibussowitsch /*@ 9515f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9516f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9517f108dbd7SJacob Faibussowitsch 951820f4b53cSBarry Smith Collective 9519f108dbd7SJacob Faibussowitsch 9520f108dbd7SJacob Faibussowitsch Input Parameters: 9521a1cb98faSBarry Smith + dm - The `DMPLEX` object 9522a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9523f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9524f108dbd7SJacob Faibussowitsch 9525f108dbd7SJacob Faibussowitsch Output Parameters: 952620f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9527a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9528f108dbd7SJacob Faibussowitsch 9529f108dbd7SJacob Faibussowitsch Options Database Keys: 9530a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9531f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9532f108dbd7SJacob Faibussowitsch 9533a1cb98faSBarry Smith Level: intermediate 9534a1cb98faSBarry Smith 9535f108dbd7SJacob Faibussowitsch Notes: 9536a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9537f108dbd7SJacob Faibussowitsch 9538a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9539f108dbd7SJacob Faibussowitsch 9540f108dbd7SJacob 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 9541f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9542f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9543f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9544f108dbd7SJacob Faibussowitsch 9545f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9546f108dbd7SJacob Faibussowitsch 9547a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9548f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9549f108dbd7SJacob Faibussowitsch 9550f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9551f108dbd7SJacob Faibussowitsch 95521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9553f108dbd7SJacob Faibussowitsch @*/ 9554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9555d71ae5a4SJacob Faibussowitsch { 95566ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 95576ed19f2fSJacob Faibussowitsch PetscInt *idx; 95586ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9559f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 95606ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9561f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9562f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9563f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9564f108dbd7SJacob Faibussowitsch IS glob; 9565f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9566f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9567f108dbd7SJacob Faibussowitsch 9568f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9569f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9570ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 95714f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 95726bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 95739566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 95749566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 957563a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 95766ed19f2fSJacob Faibussowitsch { 95776ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 95786ed19f2fSJacob Faibussowitsch 95799566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9580f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9581f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9582f108dbd7SJacob Faibussowitsch 95839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 958498921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9585f108dbd7SJacob Faibussowitsch } 95866ed19f2fSJacob Faibussowitsch } 9587f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 95884f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 95899566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 95909566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 95919371c9d4SSatish Balay } else { 95929371c9d4SSatish Balay *OrthQualLabel = NULL; 95939371c9d4SSatish Balay } 95949566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95959566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 95969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 95979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 95989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 95999566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 96009566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 96019566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 96029566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 96039566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 96049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 96059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 96069566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 96079566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 96089566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 96099566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 96109566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 96119566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 96126ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 96136ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9614f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9615f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9616898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9617f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9618f108dbd7SJacob Faibussowitsch 96196ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9620f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9621f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 96229566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 96239566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9624f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 96259566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 96266ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 96276ed19f2fSJacob Faibussowitsch PetscInt i; 96286ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9629f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9630f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9631f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9632f108dbd7SJacob Faibussowitsch 9633f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9634f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 96359566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9636f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 96376ed19f2fSJacob Faibussowitsch { 96386ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 96396ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 96406ed19f2fSJacob Faibussowitsch 96419566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 96429566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 96439566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 96446ed19f2fSJacob Faibussowitsch } 9645f108dbd7SJacob Faibussowitsch 9646f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9647f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9648f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9649f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9650f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9651addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9652addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9653addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9654f108dbd7SJacob Faibussowitsch } 9655addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9656addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9657addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9658f108dbd7SJacob Faibussowitsch 9659f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9660f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9661f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9662f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9663f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9664f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9665f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9666f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9667f108dbd7SJacob Faibussowitsch } 9668ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9669ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9670f108dbd7SJacob Faibussowitsch } 96719566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 96729566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9673f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 96746ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9675f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 96769566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9677f108dbd7SJacob Faibussowitsch } 9678f108dbd7SJacob Faibussowitsch } 96799566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 96809566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 96819566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 96829566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 96839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 96849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9685f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 96869566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9687f108dbd7SJacob Faibussowitsch } 96889566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9689cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 96909566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 96913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9692f108dbd7SJacob Faibussowitsch } 9693f108dbd7SJacob Faibussowitsch 9694d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 96951eb70e55SToby Isaac * interpolator construction */ 9696d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9697d71ae5a4SJacob Faibussowitsch { 96981eb70e55SToby Isaac PetscSection section, newSection, gsection; 96991eb70e55SToby Isaac PetscSF sf; 97001eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 97011eb70e55SToby Isaac 97021eb70e55SToby Isaac PetscFunctionBegin; 97031eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97044f572ea9SToby Isaac PetscAssertPointer(odm, 2); 97059566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 97069566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9707712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 97081eb70e55SToby Isaac if (!ghasConstraints) { 97099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 97101eb70e55SToby Isaac *odm = dm; 97113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97121eb70e55SToby Isaac } 97139566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 97149566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 97159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 97169566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 97179566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 97189566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 97199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 97203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97211eb70e55SToby Isaac } 97221eb70e55SToby Isaac 9723d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9724d71ae5a4SJacob Faibussowitsch { 97251eb70e55SToby Isaac DM dmco, dmfo; 97261eb70e55SToby Isaac Mat interpo; 97271eb70e55SToby Isaac Vec rscale; 97281eb70e55SToby Isaac Vec cglobalo, clocal; 97291eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 97301eb70e55SToby Isaac PetscBool regular; 97311eb70e55SToby Isaac 97321eb70e55SToby Isaac PetscFunctionBegin; 97339566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 97349566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 97359566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 97369566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 97379566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 97389566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 97399566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 97409566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 97419566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 97429566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 97439566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 97449566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 97459566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 97469566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 97479566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 97489566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 97499566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 97509566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 97519566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 97529566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 97539566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 97549566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 97559566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 97569566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 97571eb70e55SToby Isaac *shift = fglobal; 97589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 97599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 97609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 97619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 97629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 97639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 97649566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 97659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 97663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97671eb70e55SToby Isaac } 97681eb70e55SToby Isaac 9769d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9770d71ae5a4SJacob Faibussowitsch { 97711eb70e55SToby Isaac PetscObject shifto; 97721eb70e55SToby Isaac Vec shift; 97731eb70e55SToby Isaac 97741eb70e55SToby Isaac PetscFunctionBegin; 97751eb70e55SToby Isaac if (!interp) { 97761eb70e55SToby Isaac Vec rscale; 97771eb70e55SToby Isaac 97789566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 97799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 97801eb70e55SToby Isaac } else { 97819566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 97821eb70e55SToby Isaac } 97839566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 97841eb70e55SToby Isaac if (!shifto) { 97859566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 97869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 97871eb70e55SToby Isaac shifto = (PetscObject)shift; 97889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 97891eb70e55SToby Isaac } 97901eb70e55SToby Isaac shift = (Vec)shifto; 97919566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 97929566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 97939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 97943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97951eb70e55SToby Isaac } 97961eb70e55SToby Isaac 9797bceba477SMatthew G. Knepley /* Pointwise interpolation 9798bceba477SMatthew G. Knepley Just code FEM for now 9799bceba477SMatthew G. Knepley u^f = I u^c 98004ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 98014ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 98024ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9803bceba477SMatthew G. Knepley */ 9804d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9805d71ae5a4SJacob Faibussowitsch { 9806bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9807bceba477SMatthew G. Knepley PetscInt m, n; 9808a063dac3SMatthew G. Knepley void *ctx; 980968132eb9SMatthew G. Knepley DM cdm; 9810cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9811bceba477SMatthew G. Knepley 9812bceba477SMatthew G. Knepley PetscFunctionBegin; 98139566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 98149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 98159566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 98169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 981768132eb9SMatthew G. Knepley 98189566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 98199566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 98209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 98219566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 98229566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 982368132eb9SMatthew G. Knepley 98249566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 98259566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 98269566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 98279566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 98289566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 98294db47ee9SStefano Zampini if (scaling) { 98305d1c2e58SMatthew G. Knepley /* Use naive scaling */ 98319566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 98324db47ee9SStefano Zampini } 98333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9834a063dac3SMatthew G. Knepley } 9835bceba477SMatthew G. Knepley 9836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9837d71ae5a4SJacob Faibussowitsch { 98386dbf9973SLawrence Mitchell VecScatter ctx; 983990748bafSMatthew G. Knepley 9840a063dac3SMatthew G. Knepley PetscFunctionBegin; 98419566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 98429566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 98439566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 98443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9845bceba477SMatthew G. Knepley } 9846bceba477SMatthew G. Knepley 9847d71ae5a4SJacob 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[]) 9848d71ae5a4SJacob Faibussowitsch { 984900635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 985000635df3SMatthew G. Knepley PetscInt c; 985100635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 98523e9753d6SMatthew G. Knepley } 98533e9753d6SMatthew G. Knepley 9854d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9855d71ae5a4SJacob Faibussowitsch { 9856b4937a87SMatthew G. Knepley DM dmc; 9857b4937a87SMatthew G. Knepley PetscDS ds; 9858b4937a87SMatthew G. Knepley Vec ones, locmass; 9859b4937a87SMatthew G. Knepley IS cellIS; 9860b4937a87SMatthew G. Knepley PetscFormKey key; 9861b4937a87SMatthew G. Knepley PetscInt depth; 9862b4937a87SMatthew G. Knepley 9863b4937a87SMatthew G. Knepley PetscFunctionBegin; 98649566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 98659566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 98669566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 98679566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 98689566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 98699566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 98709566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 98719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 98729566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 98739566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 98749566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9875b4937a87SMatthew G. Knepley key.label = NULL; 9876b4937a87SMatthew G. Knepley key.value = 0; 9877b4937a87SMatthew G. Knepley key.field = 0; 9878b4937a87SMatthew G. Knepley key.part = 0; 98799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 98809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 98819566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 98829566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 98839566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 98849566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 98859566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 98869566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 98873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9888b4937a87SMatthew G. Knepley } 9889b4937a87SMatthew G. Knepley 9890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9891d71ae5a4SJacob Faibussowitsch { 9892bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9893bd041c0cSMatthew G. Knepley PetscInt m, n; 9894bd041c0cSMatthew G. Knepley void *ctx; 9895bd041c0cSMatthew G. Knepley DM cdm; 9896bd041c0cSMatthew G. Knepley PetscBool regular; 9897bd041c0cSMatthew G. Knepley 9898bd041c0cSMatthew G. Knepley PetscFunctionBegin; 98993e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 99003e9753d6SMatthew G. Knepley DM dmc; 99013e9753d6SMatthew G. Knepley PetscDS ds; 9902b4937a87SMatthew G. Knepley PetscWeakForm wf; 99033e9753d6SMatthew G. Knepley Vec u; 99043e9753d6SMatthew G. Knepley IS cellIS; 990506ad1575SMatthew G. Knepley PetscFormKey key; 99063e9753d6SMatthew G. Knepley PetscInt depth; 99073e9753d6SMatthew G. Knepley 99089566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 99099566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 99109566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99119566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 99129566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 99139566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99149566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 99158d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 99169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99179566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99189566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 99196528b96dSMatthew G. Knepley key.label = NULL; 99206528b96dSMatthew G. Knepley key.value = 0; 99216528b96dSMatthew G. Knepley key.field = 0; 992206ad1575SMatthew G. Knepley key.part = 0; 99239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 99249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99258d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 99269566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99273e9753d6SMatthew G. Knepley } else { 99289566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 99299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 99309566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 99319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9932bd041c0cSMatthew G. Knepley 99339566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 99349566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 99359566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 99369566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9937bd041c0cSMatthew G. Knepley 99389566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99399566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99409566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 99419566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 99423e9753d6SMatthew G. Knepley } 99439566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 99443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9945bd041c0cSMatthew G. Knepley } 9946bd041c0cSMatthew G. Knepley 99470aef6b92SMatthew G. Knepley /*@ 99480aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 99490aef6b92SMatthew G. Knepley 99500aef6b92SMatthew G. Knepley Input Parameter: 9951a1cb98faSBarry Smith . dm - The `DMPLEX` object 99520aef6b92SMatthew G. Knepley 99530aef6b92SMatthew G. Knepley Output Parameter: 99540aef6b92SMatthew G. Knepley . regular - The flag 99550aef6b92SMatthew G. Knepley 99560aef6b92SMatthew G. Knepley Level: intermediate 99570aef6b92SMatthew G. Knepley 99581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 99590aef6b92SMatthew G. Knepley @*/ 9960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 9961d71ae5a4SJacob Faibussowitsch { 99620aef6b92SMatthew G. Knepley PetscFunctionBegin; 99630aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99644f572ea9SToby Isaac PetscAssertPointer(regular, 2); 99650aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 99663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99670aef6b92SMatthew G. Knepley } 99680aef6b92SMatthew G. Knepley 99690aef6b92SMatthew G. Knepley /*@ 99700aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 99710aef6b92SMatthew G. Knepley 99720aef6b92SMatthew G. Knepley Input Parameters: 9973a1cb98faSBarry Smith + dm - The `DMPLEX` object 99740aef6b92SMatthew G. Knepley - regular - The flag 99750aef6b92SMatthew G. Knepley 99760aef6b92SMatthew G. Knepley Level: intermediate 99770aef6b92SMatthew G. Knepley 99781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 99790aef6b92SMatthew G. Knepley @*/ 9980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 9981d71ae5a4SJacob Faibussowitsch { 99820aef6b92SMatthew G. Knepley PetscFunctionBegin; 99830aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99840aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 99853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99860aef6b92SMatthew G. Knepley } 99870aef6b92SMatthew G. Knepley 9988a68b90caSToby Isaac /*@ 9989f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 9990a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 9991a68b90caSToby Isaac 9992a1cb98faSBarry Smith Not Collective 9993a68b90caSToby Isaac 9994f899ff85SJose E. Roman Input Parameter: 9995a1cb98faSBarry Smith . dm - The `DMPLEX` object 9996a68b90caSToby Isaac 9997a68b90caSToby Isaac Output Parameters: 999820f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 999920f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10000a68b90caSToby Isaac 10001a68b90caSToby Isaac Level: intermediate 10002a68b90caSToby Isaac 100031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10004a68b90caSToby Isaac @*/ 10005d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10006d71ae5a4SJacob Faibussowitsch { 10007a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10008a68b90caSToby Isaac 10009a68b90caSToby Isaac PetscFunctionBegin; 10010a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100119566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10012a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10013a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 100143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10015a68b90caSToby Isaac } 10016a68b90caSToby Isaac 10017a68b90caSToby Isaac /*@ 10018a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10019a68b90caSToby Isaac 1002020f4b53cSBarry Smith Collective 10021a68b90caSToby Isaac 10022a68b90caSToby Isaac Input Parameters: 10023a1cb98faSBarry Smith + dm - The `DMPLEX` object 10024a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10025a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10026a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10027a68b90caSToby Isaac 10028a68b90caSToby Isaac Level: intermediate 10029a68b90caSToby Isaac 10030a1cb98faSBarry Smith Notes: 10031a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10032a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10033a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10034a4e35b19SJacob Faibussowitsch 10035a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10036a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10037a1cb98faSBarry Smith 1003820f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10039a1cb98faSBarry Smith 100401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10041a68b90caSToby Isaac @*/ 10042d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10043d71ae5a4SJacob Faibussowitsch { 10044a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10045e228b242SToby Isaac PetscMPIInt result; 10046a68b90caSToby Isaac 10047a68b90caSToby Isaac PetscFunctionBegin; 10048a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10049e228b242SToby Isaac if (anchorSection) { 10050e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 100519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 100521dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10053e228b242SToby Isaac } 10054e228b242SToby Isaac if (anchorIS) { 10055e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 100569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 100571dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10058e228b242SToby Isaac } 10059a68b90caSToby Isaac 100609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 100619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10062a68b90caSToby Isaac plex->anchorSection = anchorSection; 10063a68b90caSToby Isaac 100649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 100659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10066a68b90caSToby Isaac plex->anchorIS = anchorIS; 10067a68b90caSToby Isaac 10068cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10069a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10070a68b90caSToby Isaac const PetscInt *anchors; 10071a68b90caSToby Isaac 100729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 100739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 100749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10075a68b90caSToby Isaac for (a = 0; a < size; a++) { 10076a68b90caSToby Isaac PetscInt p; 10077a68b90caSToby Isaac 10078a68b90caSToby Isaac p = anchors[a]; 10079a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10080a68b90caSToby Isaac PetscInt dof; 10081a68b90caSToby Isaac 100829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10083a68b90caSToby Isaac if (dof) { 100849566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1008563a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10086a68b90caSToby Isaac } 10087a68b90caSToby Isaac } 10088a68b90caSToby Isaac } 100899566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10090a68b90caSToby Isaac } 10091f7c74593SToby Isaac /* reset the generic constraints */ 100929566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 100933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10094a68b90caSToby Isaac } 10095a68b90caSToby Isaac 10096d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10097d71ae5a4SJacob Faibussowitsch { 10098f7c74593SToby Isaac PetscSection anchorSection; 100996995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10100a68b90caSToby Isaac 10101a68b90caSToby Isaac PetscFunctionBegin; 10102a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101039566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 101049566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 101059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 101066995de1eSToby Isaac if (numFields) { 10107719ab38cSToby Isaac PetscInt f; 101089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10109719ab38cSToby Isaac 10110719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10111719ab38cSToby Isaac PetscInt numComp; 10112719ab38cSToby Isaac 101139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 101149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10115719ab38cSToby Isaac } 101166995de1eSToby Isaac } 101179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 101196995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 101206995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 101216995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 101229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10123a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 101249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10125a68b90caSToby Isaac if (dof) { 101269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 101279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10128a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 101299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 101309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10131a68b90caSToby Isaac } 10132a68b90caSToby Isaac } 10133a68b90caSToby Isaac } 101349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 101359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 101363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10137a68b90caSToby Isaac } 10138a68b90caSToby Isaac 10139d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10140d71ae5a4SJacob Faibussowitsch { 10141f7c74593SToby Isaac PetscSection aSec; 10142ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 101430ac89760SToby Isaac const PetscInt *anchors; 101440ac89760SToby Isaac PetscInt numFields, f; 1014566ad2231SToby Isaac IS aIS; 10146e19f7ee6SMark Adams MatType mtype; 10147e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 101480ac89760SToby Isaac 101490ac89760SToby Isaac PetscFunctionBegin; 101500ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 101529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 101539566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 101549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 101559566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 101569566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 101579566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 101589566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10159e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10160e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10161e19f7ee6SMark Adams else mtype = MATSEQAIJ; 101629566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 101639566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 101649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 101656995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 101669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 101679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 101689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 101690ac89760SToby Isaac i[0] = 0; 101709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 101710ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10172f19733c5SToby Isaac PetscInt rDof, rOff, r; 10173f19733c5SToby Isaac 101749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10175f19733c5SToby Isaac if (!rDof) continue; 101769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 101770ac89760SToby Isaac if (numFields) { 101780ac89760SToby Isaac for (f = 0; f < numFields; f++) { 101790ac89760SToby Isaac annz = 0; 10180f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10181f19733c5SToby Isaac a = anchors[rOff + r]; 10182ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 101839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 101840ac89760SToby Isaac annz += aDof; 101850ac89760SToby Isaac } 101869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 101879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10188ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 101890ac89760SToby Isaac } 101902f7452b8SBarry Smith } else { 101910ac89760SToby Isaac annz = 0; 101929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 101930ac89760SToby Isaac for (q = 0; q < dof; q++) { 10194ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10195ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 101969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 101970ac89760SToby Isaac annz += aDof; 101980ac89760SToby Isaac } 101999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10201ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102020ac89760SToby Isaac } 102030ac89760SToby Isaac } 102040ac89760SToby Isaac nnz = i[m]; 102059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 102060ac89760SToby Isaac offset = 0; 102070ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 102080ac89760SToby Isaac if (numFields) { 102090ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102110ac89760SToby Isaac for (q = 0; q < dof; q++) { 102120ac89760SToby Isaac PetscInt rDof, rOff, r; 102139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102150ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102160ac89760SToby Isaac PetscInt s; 102170ac89760SToby Isaac 102180ac89760SToby Isaac a = anchors[rOff + r]; 10219ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10222ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102230ac89760SToby Isaac } 102240ac89760SToby Isaac } 102250ac89760SToby Isaac } 102262f7452b8SBarry Smith } else { 102279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102280ac89760SToby Isaac for (q = 0; q < dof; q++) { 102290ac89760SToby Isaac PetscInt rDof, rOff, r; 102309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102320ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102330ac89760SToby Isaac PetscInt s; 102340ac89760SToby Isaac 102350ac89760SToby Isaac a = anchors[rOff + r]; 10236ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 102389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10239ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102400ac89760SToby Isaac } 102410ac89760SToby Isaac } 102420ac89760SToby Isaac } 102430ac89760SToby Isaac } 102449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 102459566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 102469566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 102479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 102483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102490ac89760SToby Isaac } 102500ac89760SToby Isaac 10251d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10252d71ae5a4SJacob Faibussowitsch { 10253f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10254f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1025566ad2231SToby Isaac Mat cMat; 1025666ad2231SToby Isaac 1025766ad2231SToby Isaac PetscFunctionBegin; 1025866ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102599566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1026066ad2231SToby Isaac if (anchorSection) { 1026144a7f3ddSMatthew G. Knepley PetscInt Nf; 10262e228b242SToby Isaac 102639566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 102649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 102659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 102669566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 102679566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 102689566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 102699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 102709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1027166ad2231SToby Isaac } 102723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1027366ad2231SToby Isaac } 10274a93c429eSMatthew G. Knepley 10275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10276d71ae5a4SJacob Faibussowitsch { 10277a93c429eSMatthew G. Knepley IS subis; 10278a93c429eSMatthew G. Knepley PetscSection section, subsection; 10279a93c429eSMatthew G. Knepley 10280a93c429eSMatthew G. Knepley PetscFunctionBegin; 102819566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1028228b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1028328b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10284a93c429eSMatthew G. Knepley /* Create subdomain */ 102859566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10286a93c429eSMatthew G. Knepley /* Create submodel */ 102879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 102889566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 102899566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 102909566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 102919566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10292a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10293a93c429eSMatthew G. Knepley if (is) { 10294a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10295a93c429eSMatthew G. Knepley IS spIS; 10296a93c429eSMatthew G. Knepley const PetscInt *spmap; 10297a93c429eSMatthew G. Knepley PetscInt *subIndices; 10298a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10299a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10300a93c429eSMatthew G. Knepley 103019566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 103029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 103039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 103049566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 103059566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 103069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10307a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10308a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10309a93c429eSMatthew G. Knepley 103109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10311a93c429eSMatthew G. Knepley if (gdof > 0) { 10312a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10313a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10314a93c429eSMatthew G. Knepley 103159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 103169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10317a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10318a93c429eSMatthew G. Knepley } 10319a93c429eSMatthew G. Knepley subSize += pSubSize; 10320a93c429eSMatthew G. Knepley if (pSubSize) { 10321a93c429eSMatthew G. Knepley if (bs < 0) { 10322a93c429eSMatthew G. Knepley bs = pSubSize; 10323a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10324a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10325a93c429eSMatthew G. Knepley bs = 1; 10326a93c429eSMatthew G. Knepley } 10327a93c429eSMatthew G. Knepley } 10328a93c429eSMatthew G. Knepley } 10329a93c429eSMatthew G. Knepley } 10330a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 103319371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 103329371c9d4SSatish Balay bsLocal[1] = bs; 103339566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 103349371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 103359371c9d4SSatish Balay bs = 1; 103369371c9d4SSatish Balay } else { 103379371c9d4SSatish Balay bs = bsMinMax[0]; 103389371c9d4SSatish Balay } 103399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10340a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10341a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10342a93c429eSMatthew G. Knepley 103439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10344a93c429eSMatthew G. Knepley if (gdof > 0) { 10345a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10346a93c429eSMatthew G. Knepley 103479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10348a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10349a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10350a93c429eSMatthew G. Knepley 10351a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10352a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 103539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 103549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10355a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10356a93c429eSMatthew G. Knepley } 103579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 103589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10359ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10360a93c429eSMatthew G. Knepley } 10361a93c429eSMatthew G. Knepley } 10362a93c429eSMatthew G. Knepley } 103639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 103649566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10365a93c429eSMatthew G. Knepley if (bs > 1) { 10366a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10367a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10368a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10369a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 103709371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 103719371c9d4SSatish Balay set = 0; 103729371c9d4SSatish Balay break; 103739371c9d4SSatish Balay } 10374a93c429eSMatthew G. Knepley } 10375a93c429eSMatthew G. Knepley } 103769566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10377a93c429eSMatthew G. Knepley } 10378a93c429eSMatthew G. Knepley /* Attach nullspace */ 10379a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10380a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10381a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10382a93c429eSMatthew G. Knepley } 10383a93c429eSMatthew G. Knepley if (f < Nf) { 10384a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 103859566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 103866823f3c5SBlaise Bourdin 103879566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 103889566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10389a93c429eSMatthew G. Knepley } 10390a93c429eSMatthew G. Knepley } 103913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10392a93c429eSMatthew G. Knepley } 10393c0f0dcc3SMatthew G. Knepley 10394c0f0dcc3SMatthew G. Knepley /*@ 10395c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10396c0f0dcc3SMatthew G. Knepley 10397a1cb98faSBarry Smith Input Parameters: 10398a1cb98faSBarry Smith + dm - The `DM` 10399a1cb98faSBarry Smith - dummy - unused argument 10400a1cb98faSBarry Smith 10401a1cb98faSBarry Smith Options Database Key: 10402a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10403c0f0dcc3SMatthew G. Knepley 10404c0f0dcc3SMatthew G. Knepley Level: developer 10405c0f0dcc3SMatthew G. Knepley 104061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10407c0f0dcc3SMatthew G. Knepley @*/ 10408d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10409d71ae5a4SJacob Faibussowitsch { 10410b665b14eSToby Isaac PetscLogHandler default_handler; 10411b665b14eSToby Isaac 104122611ad71SToby Isaac PetscFunctionBegin; 104132611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10414b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10415b665b14eSToby Isaac if (default_handler) { 10416c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10417c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10418c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10419c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10420c0f0dcc3SMatthew G. Knepley const char *name; 10421c0f0dcc3SMatthew G. Knepley 104229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 104239566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 104249566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 104259566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10426b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10427c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10428c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10429c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1043063a3b9bcSJacob 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))); 104312611ad71SToby Isaac } else { 10432b665b14eSToby 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."); 104332611ad71SToby Isaac } 104343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10435c0f0dcc3SMatthew G. Knepley } 10436