1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11552f7358SJed Brown 12552f7358SJed Brown /* Logging support */ 1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad; 14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 15552f7358SJed Brown 16f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 18f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 19f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 20f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 21f39ec787SMatthew G. Knepley "volume = {38},\n" 22f39ec787SMatthew G. Knepley "number = {5},\n" 23f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 24f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 25f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 26f39ec787SMatthew G. Knepley "year = {2016},\n" 27f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 28f39ec787SMatthew G. Knepley 295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 30552f7358SJed Brown 31e5337592SStefano Zampini /*@ 329318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 339318fe57SMatthew G. Knepley 349318fe57SMatthew G. Knepley Input Parameter: 35a1cb98faSBarry Smith . dm - The `DMPLEX` object 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley Output Parameter: 389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley Level: intermediate 419318fe57SMatthew G. Knepley 42a1cb98faSBarry Smith Note: 43a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 44a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 45a1cb98faSBarry Smith 461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 479318fe57SMatthew G. Knepley @*/ 48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 49d71ae5a4SJacob Faibussowitsch { 509318fe57SMatthew G. Knepley DMPolytopeType ct; 519318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 529318fe57SMatthew G. Knepley 539318fe57SMatthew G. Knepley PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 559371c9d4SSatish Balay if (cEnd <= cStart) { 569371c9d4SSatish Balay *simplex = PETSC_FALSE; 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589371c9d4SSatish Balay } 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 609318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629318fe57SMatthew G. Knepley } 639318fe57SMatthew G. Knepley 649318fe57SMatthew G. Knepley /*@ 65412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 66e5337592SStefano Zampini 67d8d19677SJose E. Roman Input Parameters: 68a1cb98faSBarry Smith + dm - The `DMPLEX` object 69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 70e5337592SStefano Zampini 71e5337592SStefano Zampini Output Parameters: 72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7340196513SBarry Smith - cEnd - The upper bound on "normal" cells 74e5337592SStefano Zampini 75412e9a14SMatthew G. Knepley Level: developer 76e5337592SStefano Zampini 77a1cb98faSBarry Smith Note: 785ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 79a1cb98faSBarry Smith 802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 81e5337592SStefano Zampini @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 83d71ae5a4SJacob Faibussowitsch { 845ae96e2bSMatthew G. Knepley DMLabel ctLabel; 855ae96e2bSMatthew G. Knepley IS valueIS; 865ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 875ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 88e5337592SStefano Zampini 89e5337592SStefano Zampini PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 915ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 925ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 935ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 945ae96e2bSMatthew G. Knepley if (!Nct) cS = cE = 0; 955ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 96c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 975ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 985ae96e2bSMatthew G. Knepley 995ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1005ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1015ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1025ae96e2bSMatthew G. Knepley break; 1035ae96e2bSMatthew G. Knepley } 104c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1055ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1065ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1075ae96e2bSMatthew G. Knepley // Check that a point has the right height 1085ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1095ae96e2bSMatthew G. Knepley if (ht != height) continue; 1105ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1115ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1125ae96e2bSMatthew G. Knepley } 1135ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 114695799ffSMatthew G. Knepley // Reset label for fast lookup 115695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 116412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 117412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119e5337592SStefano Zampini } 120e5337592SStefano Zampini 1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1229c600e38SMatt McGurn { 1239c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1249c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1259c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1269c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1279c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1289c600e38SMatt McGurn 1299c600e38SMatt McGurn PetscFunctionBegin; 1309c600e38SMatt McGurn 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); 1087bd3611e6SMatthew G. Knepley n = 4; 10889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10891dca8a05SBarry 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); 10909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10910588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10930588280cSMatthew G. Knepley if (!useColors) { 10940588280cSMatthew G. Knepley numColors = 3; 10959566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10960588280cSMatthew G. Knepley } 10979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10980588280cSMatthew G. Knepley if (!useColors) { 10990588280cSMatthew G. Knepley numLColors = 4; 11009566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11010588280cSMatthew G. Knepley } 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1103b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11051dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1106202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1108fe1cc32dSStefano Zampini 1109fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1114fe1cc32dSStefano Zampini if (lflg) { 1115fe1cc32dSStefano Zampini DMLabel lbl; 1116fe1cc32dSStefano Zampini 11179566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1118fe1cc32dSStefano Zampini if (lbl) { 1119fe1cc32dSStefano Zampini PetscInt val, defval; 1120fe1cc32dSStefano Zampini 11219566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11229566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1123fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1124fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1125fe1cc32dSStefano Zampini PetscInt closureSize; 1126fe1cc32dSStefano Zampini 11279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1128fe1cc32dSStefano Zampini if (val == defval) continue; 1129fe1cc32dSStefano Zampini 11309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 113148a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini } 1135fe1cc32dSStefano Zampini } 1136fe1cc32dSStefano Zampini 11379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11410588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1142552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1143552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1144552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11455f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11460588280cSMatthew G. Knepley if (size > 1) { 11479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1148770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114963a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 115063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1151770b213bSMatthew G Knepley } 11529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11530588280cSMatthew G. Knepley } 1154b7f6ffafSMatthew G. Knepley if (drawHasse) { 1155b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1156b7f6ffafSMatthew G. Knepley 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 116163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1169b7f6ffafSMatthew G. Knepley } 11709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1171fe1cc32dSStefano Zampini 1172552f7358SJed Brown /* Plot vertices */ 11739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1175552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1176552f7358SJed Brown PetscInt off, dof, d; 11770588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1178552f7358SJed Brown 1179fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118363a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11840588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11850588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1186c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11870588280cSMatthew G. Knepley } 11880588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11899371c9d4SSatish Balay if (dim == 3) { 11909371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11919371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11929371c9d4SSatish Balay tcoords[2] = -tmp; 11939371c9d4SSatish Balay } 1194552f7358SJed Brown for (d = 0; d < dof; ++d) { 11959566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1197552f7358SJed Brown } 1198b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1199b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 12000588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12010588280cSMatthew G. Knepley PetscInt val; 12029566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12039371c9d4SSatish Balay if (val >= 0) { 12049371c9d4SSatish Balay color = lcolors[l % numLColors]; 12059371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12069371c9d4SSatish Balay break; 12079371c9d4SSatish Balay } 12080588280cSMatthew G. Knepley } 1209b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 121063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1211b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12131baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1214552f7358SJed Brown } 12159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12169566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1217b7f6ffafSMatthew G. Knepley /* Plot edges */ 1218b7f6ffafSMatthew G. Knepley if (plotEdges) { 12199566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1221b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1222b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1223b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1224b7f6ffafSMatthew G. Knepley 1225b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1233b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1234b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1235b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1236b7f6ffafSMatthew G. Knepley } 1237b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12389371c9d4SSatish Balay if (dim == 3) { 12399371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12409371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12419371c9d4SSatish Balay tcoords[2] = -tmp; 12429371c9d4SSatish Balay } 1243b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12449566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1246b7f6ffafSMatthew G. Knepley } 1247b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1248b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1249b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1250b7f6ffafSMatthew G. Knepley PetscInt val; 1251bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12529371c9d4SSatish Balay if (val >= 0) { 12539371c9d4SSatish Balay color = lcolors[l % numLColors]; 12549371c9d4SSatish Balay break; 12559371c9d4SSatish Balay } 1256b7f6ffafSMatthew G. Knepley } 125763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1258b7f6ffafSMatthew G. Knepley } 12599566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1262b7f6ffafSMatthew G. Knepley } 1263846a3e8bSMatthew G. Knepley /* Plot cells */ 1264b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1265846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1266846a3e8bSMatthew G. Knepley const PetscInt *cone; 1267846a3e8bSMatthew G. Knepley 1268fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1269846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1270846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1271846a3e8bSMatthew G. Knepley PetscInt val; 12729566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12739371c9d4SSatish Balay if (val >= 0) { 12749371c9d4SSatish Balay color = lcolors[l % numLColors]; 12759371c9d4SSatish Balay break; 12769371c9d4SSatish Balay } 1277846a3e8bSMatthew G. Knepley } 12789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1280846a3e8bSMatthew G. Knepley } 1281846a3e8bSMatthew G. Knepley } else { 1282b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1283846a3e8bSMatthew G. Knepley 1284b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1285b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1286fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1288c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1289b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1290b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1291b7f6ffafSMatthew G. Knepley 12929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1294b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1295b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1296b7f6ffafSMatthew G. Knepley 12979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129863a3b9bcSJacob 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)); 1299b7f6ffafSMatthew G. Knepley } 1300b7f6ffafSMatthew G. Knepley } else { 1301b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1302b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1303b7f6ffafSMatthew G. Knepley 13049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1305846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1306846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1307846a3e8bSMatthew G. Knepley 1308b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1309846a3e8bSMatthew G. Knepley } 13109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1311b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1312b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1313b7f6ffafSMatthew G. Knepley 1314b7f6ffafSMatthew G. Knepley if (v > 0) { 1315b7f6ffafSMatthew G. Knepley if (plotEdges) { 1316b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1317b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1318b7f6ffafSMatthew G. Knepley 13199371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13209371c9d4SSatish Balay endpoints[1] = vertex; 13219566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132263a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13251baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1326b7f6ffafSMatthew G. Knepley } 132763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1328b7f6ffafSMatthew G. Knepley } 13299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1331846a3e8bSMatthew G. Knepley } 1332846a3e8bSMatthew G. Knepley } 1333b7f6ffafSMatthew G. Knepley } 1334846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1335846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1336846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1337c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1338c713ec31SMatthew G. Knepley const PetscScalar *array; 1339c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1340c713ec31SMatthew G. Knepley PetscBool isDG; 1341846a3e8bSMatthew G. Knepley 1342fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1343c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1344c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1345c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1347c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1348c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1349c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1350846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1351846a3e8bSMatthew G. Knepley } 1352846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13539371c9d4SSatish Balay if (cdim == 3) { 13549371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13559371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13569371c9d4SSatish Balay tcoords[2] = -tmp; 13579371c9d4SSatish Balay } 1358ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1359846a3e8bSMatthew G. Knepley } 1360ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1361c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1362c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13639566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1365846a3e8bSMatthew G. Knepley } 1366b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1367b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1368846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1369846a3e8bSMatthew G. Knepley PetscInt val; 13709566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13719371c9d4SSatish Balay if (val >= 0) { 13729371c9d4SSatish Balay color = lcolors[l % numLColors]; 13739371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13749371c9d4SSatish Balay break; 13759371c9d4SSatish Balay } 1376846a3e8bSMatthew G. Knepley } 1377b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1379b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 138063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13811baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1382846a3e8bSMatthew G. Knepley } 1383b7f6ffafSMatthew G. Knepley if (drawHasse) { 1384b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1390552f7358SJed Brown 1391b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1397b7f6ffafSMatthew G. Knepley 1398b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1404b7f6ffafSMatthew G. Knepley 1405b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1406b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1407b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1408b7f6ffafSMatthew G. Knepley 14099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 141148a46eb9SPierre 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)); 14120588280cSMatthew G. Knepley } 14130588280cSMatthew G. Knepley } 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14189566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14199566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14209566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14219566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14229566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14230f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14240f7d6e4aSStefano Zampini Vec cown, acown; 14250f7d6e4aSStefano Zampini VecScatter sct; 14260f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14270f7d6e4aSStefano Zampini IS gid, acis; 14280f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14290f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14300f7d6e4aSStefano Zampini PetscScalar *array, nid; 14310f7d6e4aSStefano Zampini const PetscInt *idxs; 14320f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14330f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14340f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14350f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14360f7d6e4aSStefano Zampini 14379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1439b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14410f7d6e4aSStefano Zampini #endif 14420f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14450f7d6e4aSStefano Zampini d1 = 0; 14469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14470f7d6e4aSStefano Zampini nid = d2; 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14510f7d6e4aSStefano Zampini } else nid = 0.0; 14520f7d6e4aSStefano Zampini 14530f7d6e4aSStefano Zampini /* Get connectivity */ 14549566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14559566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14560f7d6e4aSStefano Zampini 14570f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14620f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14630f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14640f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14650f7d6e4aSStefano Zampini } 14669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146763a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14699566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14700f7d6e4aSStefano Zampini 14710f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14739566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14749566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14759566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14760f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14829566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14840f7d6e4aSStefano Zampini 14850f7d6e4aSStefano Zampini /* compute edgeCut */ 14860f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14919566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14920f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14930f7d6e4aSStefano Zampini PetscInt totl; 14940f7d6e4aSStefano Zampini 14950f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14969566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14970f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14980f7d6e4aSStefano Zampini if (work[i] < 0) { 14990f7d6e4aSStefano Zampini ect += 1; 15000f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 15010f7d6e4aSStefano Zampini } 15020f7d6e4aSStefano Zampini } 15030f7d6e4aSStefano Zampini } 15049566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15060f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15070f7d6e4aSStefano Zampini lm[1] = -numVertices; 15081c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150963a3b9bcSJacob 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])); 15100f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15110f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15120f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15131c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1515b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 151663a3b9bcSJacob 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.)); 15170f7d6e4aSStefano Zampini #else 151863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15190f7d6e4aSStefano Zampini #endif 15209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15219566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15229566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1524552f7358SJed Brown } else { 1525412e9a14SMatthew G. Knepley const char *name; 1526d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1527412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1528d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1529ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15309318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1531412e9a14SMatthew G. Knepley MPI_Comm comm; 1532412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1533552f7358SJed Brown 15349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 154063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 154163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154263a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15452827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1546d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15479566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15489566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1549412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1550412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1551412e9a14SMatthew G. Knepley 15529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15539566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1554412e9a14SMatthew G. Knepley ict = ct0; 15559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1556412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1557412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1558412e9a14SMatthew G. Knepley DMPolytopeType ct; 1559412e9a14SMatthew G. Knepley 15609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1561412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1562412e9a14SMatthew G. Knepley else ++Nc[1]; 1563412e9a14SMatthew G. Knepley } 1564ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15679566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1569834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1570dd400576SPatrick Sanan if (rank == 0) { 157163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157263a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157363a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1574834065abSMatthew G. Knepley } 1575cbb7f117SMark Adams } 1576ca7bf7eeSMatthew G. Knepley } else { 1577ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1578ca7bf7eeSMatthew G. Knepley 15799371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15809371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15819566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15829371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15839371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15849566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1585ca7bf7eeSMatthew G. Knepley if (d == depth) { 15869371c9d4SSatish Balay locMinMax[0] = gcNum; 15879371c9d4SSatish Balay locMinMax[1] = gcNum; 15889566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1589ca7bf7eeSMatthew G. Knepley } 159063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15929566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15939566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1594ca7bf7eeSMatthew G. Knepley } 15959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1596552f7358SJed Brown } 15979566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15989318fe57SMatthew G. Knepley { 15999318fe57SMatthew G. Knepley const PetscReal *maxCell; 16009318fe57SMatthew G. Knepley const PetscReal *L; 16016858538eSMatthew G. Knepley PetscBool localized; 16029318fe57SMatthew G. Knepley 16034fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16056858538eSMatthew G. Knepley if (L || localized) { 16066858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16086858538eSMatthew G. Knepley if (L) { 16096858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16109318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16116858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16126858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16139318fe57SMatthew G. Knepley } 16146858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16156858538eSMatthew G. Knepley } 16166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16189318fe57SMatthew G. Knepley } 16199318fe57SMatthew G. Knepley } 16209566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16219566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1622a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1623a57dd577SMatthew G Knepley DMLabel label; 1624a57dd577SMatthew G Knepley const char *name; 1625a57dd577SMatthew G Knepley IS valueIS; 1626a57dd577SMatthew G Knepley const PetscInt *values; 1627a57dd577SMatthew G Knepley PetscInt numValues, v; 1628a57dd577SMatthew G Knepley 16299566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16319566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16339566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1636a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1637a57dd577SMatthew G Knepley PetscInt size; 1638a57dd577SMatthew G Knepley 16399566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16409566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 164163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1642a57dd577SMatthew G Knepley } 16439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1647a57dd577SMatthew G Knepley } 1648c1cad2e7SMatthew G. Knepley { 1649c1cad2e7SMatthew G. Knepley char **labelNames; 1650c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1651c1cad2e7SMatthew G. Knepley PetscBool flg; 1652c1cad2e7SMatthew G. Knepley 16539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1655c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1656c1cad2e7SMatthew G. Knepley DMLabel label; 1657c1cad2e7SMatthew G. Knepley 16589566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1659c1cad2e7SMatthew G. Knepley if (flg) { 16609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16619566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1662c1cad2e7SMatthew G. Knepley } 16639566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1664c1cad2e7SMatthew G. Knepley } 16659566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1666c1cad2e7SMatthew G. Knepley } 166734aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166834aa8a36SMatthew G. Knepley if (dm->Nf) { 166934aa8a36SMatthew G. Knepley PetscInt f; 167034aa8a36SMatthew G. Knepley 167134aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167234aa8a36SMatthew G. Knepley const char *name; 167334aa8a36SMatthew G. Knepley 16749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16759566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16779566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167834aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16799566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16809566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 168134aa8a36SMatthew G. Knepley } else { 16829566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16839566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168434aa8a36SMatthew G. Knepley } 16859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168634aa8a36SMatthew G. Knepley } 168734aa8a36SMatthew G. Knepley } 16889566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16898e7ff633SMatthew G. Knepley if (cdm) { 16909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16919f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16929566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16948e7ff633SMatthew G. Knepley } 1695552f7358SJed Brown } 16963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1697552f7358SJed Brown } 1698552f7358SJed Brown 1699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1700d71ae5a4SJacob Faibussowitsch { 1701e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1702e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1703a12d352dSMatthew G. Knepley PetscInt cdim; 1704e5c487bfSMatthew G. Knepley 1705e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1709e5c487bfSMatthew G. Knepley switch (ct) { 1710a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1711a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1712a12d352dSMatthew G. Knepley switch (cdim) { 17139371c9d4SSatish Balay case 1: { 1714a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1715a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1716a12d352dSMatthew G. Knepley 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17189566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17199566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17209371c9d4SSatish Balay } break; 17219371c9d4SSatish Balay case 2: { 1722a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1723a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1724a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1725a12d352dSMatthew G. Knepley 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17279566063dSJacob 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)); 17289566063dSJacob 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)); 17299371c9d4SSatish Balay } break; 1730d71ae5a4SJacob Faibussowitsch default: 1731d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1732a12d352dSMatthew G. Knepley } 1733a12d352dSMatthew G. Knepley break; 1734e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17359371c9d4SSatish 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)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17379566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17389566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1739e5c487bfSMatthew G. Knepley break; 1740e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17419371c9d4SSatish 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)); 17429371c9d4SSatish 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)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17459566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17469566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1747e5c487bfSMatthew G. Knepley break; 17489f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17499f4ada15SMatthew 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)); 17509f4ada15SMatthew 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)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17549f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17559f4ada15SMatthew G. Knepley break; 1756d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1757d71ae5a4SJacob Faibussowitsch break; 1758d71ae5a4SJacob Faibussowitsch default: 1759d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1760e5c487bfSMatthew G. Knepley } 17613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1762e5c487bfSMatthew G. Knepley } 1763e5c487bfSMatthew G. Knepley 1764*c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1765d71ae5a4SJacob Faibussowitsch { 1766e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1767e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1768*c5aedaa3SMatthew G. Knepley PetscInt fillColor; 1769e5c487bfSMatthew G. Knepley 1770e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1772e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1773*c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1774*c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1775*c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 17769371c9d4SSatish Balay } 1777*c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1778e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1779e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1780*c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1781*c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1782*c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1783e5c487bfSMatthew G. Knepley } 17849566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1785*c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 17869566063dSJacob 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)); 17879566063dSJacob 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)); 1788e5c487bfSMatthew G. Knepley } 1789e5c487bfSMatthew G. Knepley } 1790*c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1791*c5aedaa3SMatthew G. Knepley } 1792*c5aedaa3SMatthew G. Knepley 1793*c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1794*c5aedaa3SMatthew G. Knepley { 1795*c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1796*c5aedaa3SMatthew G. Knepley 1797*c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1798*c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1799*c5aedaa3SMatthew G. Knepley switch (ct) { 1800*c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1801*c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1802*c5aedaa3SMatthew G. Knepley 1803*c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1804*c5aedaa3SMatthew G. Knepley } break; 1805*c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1806*c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1807*c5aedaa3SMatthew G. Knepley 1808*c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 18099371c9d4SSatish Balay } break; 1810d71ae5a4SJacob Faibussowitsch default: 1811d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1812e5c487bfSMatthew G. Knepley } 18133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1814e5c487bfSMatthew G. Knepley } 1815e5c487bfSMatthew G. Knepley 1816d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1817d71ae5a4SJacob Faibussowitsch { 1818e412dcbdSMatthew G. Knepley PetscDraw draw; 1819e412dcbdSMatthew G. Knepley DM cdm; 1820e412dcbdSMatthew G. Knepley PetscSection coordSection; 1821e412dcbdSMatthew G. Knepley Vec coordinates; 1822c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1823e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1824*c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1825*c5aedaa3SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv; 1826e412dcbdSMatthew G. Knepley 1827e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 182963a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1830*c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1831*c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1832*c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 18339566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18349566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18369566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18399566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1840e412dcbdSMatthew G. Knepley 18419566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18429566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18433ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18449566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1845e412dcbdSMatthew G. Knepley 1846c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18479566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18489566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1849e412dcbdSMatthew G. Knepley 1850cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1851cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1852c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1853ba2698f1SMatthew G. Knepley PetscInt numCoords; 1854c9c77995SMatthew G. Knepley PetscBool isDG; 1855cf3064d3SMatthew G. Knepley 1856c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18571baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18581baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1859c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1860cf3064d3SMatthew G. Knepley } 18619566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18629566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18639566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18649566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1866e412dcbdSMatthew G. Knepley } 1867e412dcbdSMatthew G. Knepley 1868e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1869e44f6aebSMatthew G. Knepley { 1870e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1871e44f6aebSMatthew G. Knepley PetscFE fe; 1872e44f6aebSMatthew G. Knepley PetscSpace sp; 1873e44f6aebSMatthew G. Knepley PetscClassId id; 1874e44f6aebSMatthew G. Knepley PetscInt degree; 1875e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1876e44f6aebSMatthew G. Knepley 1877e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1878e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1879e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1880e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1881e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1882e44f6aebSMatthew G. Knepley *hdm = dm; 1883e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1884e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1885e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1886e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1887e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1888e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1889e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1890e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1891e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1892e44f6aebSMatthew G. Knepley Mat In; 1893e44f6aebSMatthew G. Knepley Vec cl, rcl; 1894e44f6aebSMatthew G. Knepley 1895e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1896*c5aedaa3SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1897e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1898e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1899e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1900e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1901e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1902e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1903e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1904e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1905e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1906e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1907e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1908e44f6aebSMatthew G. Knepley odm = rdm; 1909e44f6aebSMatthew G. Knepley } 1910e44f6aebSMatthew G. Knepley *hdm = rdm; 1911e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1912e44f6aebSMatthew G. Knepley } 1913e44f6aebSMatthew G. Knepley 19141e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19151e50132fSMatthew G. Knepley #include <exodusII.h> 19166823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19171e50132fSMatthew G. Knepley #endif 19181e50132fSMatthew G. Knepley 1919d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1920d71ae5a4SJacob Faibussowitsch { 19215f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1922002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1923552f7358SJed Brown 1924552f7358SJed Brown PetscFunctionBegin; 1925552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1926552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19335f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1934552f7358SJed Brown if (iascii) { 19358135c375SStefano Zampini PetscViewerFormat format; 19369566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19371baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19381baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1939c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1940c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19419566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1942c6ccd67eSMatthew G. Knepley #else 1943c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1944552f7358SJed Brown #endif 1945e412dcbdSMatthew G. Knepley } else if (isvtk) { 19469566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1947e412dcbdSMatthew G. Knepley } else if (isdraw) { 1948e44f6aebSMatthew G. Knepley DM hdm; 1949e44f6aebSMatthew G. Knepley 1950e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1951e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1952e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19538135c375SStefano Zampini } else if (isglvis) { 19549566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19551e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19561e50132fSMatthew G. Knepley } else if (isexodus) { 19576823f3c5SBlaise Bourdin /* 19586823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19596823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1960da81f932SPierre Jolivet with ID 1, containing all cells. 19616823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19626823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19636823f3c5SBlaise Bourdin */ 19646823f3c5SBlaise Bourdin PetscInt numCS; 19659566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19666823f3c5SBlaise Bourdin if (!numCS) { 19671e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19689566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19709566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19716823f3c5SBlaise Bourdin } 19729566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19731e50132fSMatthew G. Knepley #endif 19745f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19755f34f2dcSJed Brown } else if (iscgns) { 19765f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19775f34f2dcSJed Brown #endif 19781baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1979cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19809566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1981cb3ba0daSMatthew G. Knepley if (flg) { 1982cb3ba0daSMatthew G. Knepley Vec ranks; 19839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19849566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1986cb3ba0daSMatthew G. Knepley } 1987002a2709SMatthew G. Knepley /* Optionally view a label */ 19889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1989002a2709SMatthew G. Knepley if (flg) { 1990002a2709SMatthew G. Knepley DMLabel label; 1991002a2709SMatthew G. Knepley Vec val; 1992002a2709SMatthew G. Knepley 19939566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 199428b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19959566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19969566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1998002a2709SMatthew G. Knepley } 19993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2000552f7358SJed Brown } 2001552f7358SJed Brown 20027f96f51bSksagiyam /*@ 2003a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 20047f96f51bSksagiyam 200520f4b53cSBarry Smith Collective 20067f96f51bSksagiyam 20077f96f51bSksagiyam Input Parameters: 2008a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2009a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 20107f96f51bSksagiyam 20117f96f51bSksagiyam Level: advanced 20127f96f51bSksagiyam 20131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 20147f96f51bSksagiyam @*/ 2015d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2016d71ae5a4SJacob Faibussowitsch { 20177f96f51bSksagiyam PetscBool ishdf5; 20187f96f51bSksagiyam 20197f96f51bSksagiyam PetscFunctionBegin; 20207f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20217f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20247f96f51bSksagiyam if (ishdf5) { 20257f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20267f96f51bSksagiyam PetscViewerFormat format; 20279566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20287f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20297f96f51bSksagiyam IS globalPointNumbering; 20307f96f51bSksagiyam 20319566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20329566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 203498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20357f96f51bSksagiyam #else 20367f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20377f96f51bSksagiyam #endif 20387f96f51bSksagiyam } 20399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20417f96f51bSksagiyam } 20427f96f51bSksagiyam 204377b8e257Sksagiyam /*@ 2044a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 204577b8e257Sksagiyam 204620f4b53cSBarry Smith Collective 204777b8e257Sksagiyam 204877b8e257Sksagiyam Input Parameters: 2049a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2050a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 205177b8e257Sksagiyam 205277b8e257Sksagiyam Level: advanced 205377b8e257Sksagiyam 20541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 205577b8e257Sksagiyam @*/ 2056d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2057d71ae5a4SJacob Faibussowitsch { 205877b8e257Sksagiyam PetscBool ishdf5; 205977b8e257Sksagiyam 206077b8e257Sksagiyam PetscFunctionBegin; 206177b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 206277b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 206577b8e257Sksagiyam if (ishdf5) { 206677b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 206777b8e257Sksagiyam PetscViewerFormat format; 20689566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 206977b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20709566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2071fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 207277b8e257Sksagiyam #else 207377b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 207477b8e257Sksagiyam #endif 207577b8e257Sksagiyam } 20769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207877b8e257Sksagiyam } 207977b8e257Sksagiyam 2080bd6565f1Sksagiyam /*@ 2081a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2082bd6565f1Sksagiyam 208320f4b53cSBarry Smith Collective 2084bd6565f1Sksagiyam 2085bd6565f1Sksagiyam Input Parameters: 2086a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2087a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2088bd6565f1Sksagiyam 2089bd6565f1Sksagiyam Level: advanced 2090bd6565f1Sksagiyam 20911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2092bd6565f1Sksagiyam @*/ 2093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2094d71ae5a4SJacob Faibussowitsch { 2095bd6565f1Sksagiyam PetscBool ishdf5; 2096bd6565f1Sksagiyam 2097bd6565f1Sksagiyam PetscFunctionBegin; 2098bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2099bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2102bd6565f1Sksagiyam if (ishdf5) { 2103bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2104bd6565f1Sksagiyam IS globalPointNumbering; 2105bd6565f1Sksagiyam PetscViewerFormat format; 2106bd6565f1Sksagiyam 21079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2108bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21099566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21109566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 211298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2113bd6565f1Sksagiyam #else 2114bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2115bd6565f1Sksagiyam #endif 2116bd6565f1Sksagiyam } 21179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2119bd6565f1Sksagiyam } 2120bd6565f1Sksagiyam 2121021affd3Sksagiyam /*@ 2122a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2123021affd3Sksagiyam 212420f4b53cSBarry Smith Collective 2125021affd3Sksagiyam 2126021affd3Sksagiyam Input Parameters: 2127a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2128a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 2129a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved 2130021affd3Sksagiyam 2131021affd3Sksagiyam Level: advanced 2132021affd3Sksagiyam 2133021affd3Sksagiyam Notes: 2134420bcc1bSBarry 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. 2135021affd3Sksagiyam 2136420bcc1bSBarry 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. 2137021affd3Sksagiyam 21381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2139021affd3Sksagiyam @*/ 2140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2141d71ae5a4SJacob Faibussowitsch { 2142021affd3Sksagiyam PetscBool ishdf5; 2143021affd3Sksagiyam 2144021affd3Sksagiyam PetscFunctionBegin; 2145021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2146021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2147021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21499566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2150021affd3Sksagiyam if (ishdf5) { 2151021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21529566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2153021affd3Sksagiyam #else 2154021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2155021affd3Sksagiyam #endif 2156021affd3Sksagiyam } 21579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2159021affd3Sksagiyam } 2160021affd3Sksagiyam 21613e97647fSksagiyam /*@ 21623e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21633e97647fSksagiyam 216420f4b53cSBarry Smith Collective 21653e97647fSksagiyam 21663e97647fSksagiyam Input Parameters: 2167a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2168a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2169a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 21703e97647fSksagiyam - vec - The global vector to be saved 21713e97647fSksagiyam 21723e97647fSksagiyam Level: advanced 21733e97647fSksagiyam 21743e97647fSksagiyam Notes: 2175420bcc1bSBarry 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. 21763e97647fSksagiyam 217760225df5SJacob Faibussowitsch Calling sequence: 2178a1cb98faSBarry Smith .vb 2179a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2180a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2181a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2182a1cb98faSBarry Smith DMClone(dm, §iondm); 2183a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2184a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2185a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2186a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2187a1cb98faSBarry Smith PetscSectionSetUp(section); 2188a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2189a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2190a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2191a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2192a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2193a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2194a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2195a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2196a1cb98faSBarry Smith DMDestroy(§iondm); 2197a1cb98faSBarry Smith DMDestroy(&dm); 2198a1cb98faSBarry Smith .ve 21993e97647fSksagiyam 22001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22013e97647fSksagiyam @*/ 2202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2203d71ae5a4SJacob Faibussowitsch { 22043e97647fSksagiyam PetscBool ishdf5; 22053e97647fSksagiyam 22063e97647fSksagiyam PetscFunctionBegin; 22073e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22083e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22093e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22103e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22113e97647fSksagiyam /* Check consistency */ 22123e97647fSksagiyam { 22133e97647fSksagiyam PetscSection section; 22143e97647fSksagiyam PetscBool includesConstraints; 22153e97647fSksagiyam PetscInt m, m1; 22163e97647fSksagiyam 22179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22189566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22209566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22219566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 222263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22233e97647fSksagiyam } 22249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22263e97647fSksagiyam if (ishdf5) { 22273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22289566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22293e97647fSksagiyam #else 22303e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22313e97647fSksagiyam #endif 22323e97647fSksagiyam } 22339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22353e97647fSksagiyam } 22363e97647fSksagiyam 22373e97647fSksagiyam /*@ 22383e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22393e97647fSksagiyam 224020f4b53cSBarry Smith Collective 22413e97647fSksagiyam 22423e97647fSksagiyam Input Parameters: 2243a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2244a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 224520f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm` 22463e97647fSksagiyam - vec - The local vector to be saved 22473e97647fSksagiyam 22483e97647fSksagiyam Level: advanced 22493e97647fSksagiyam 2250a1cb98faSBarry Smith Note: 225120f4b53cSBarry 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. 22523e97647fSksagiyam 225360225df5SJacob Faibussowitsch Calling sequence: 2254a1cb98faSBarry Smith .vb 2255a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2256a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2257a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2258a1cb98faSBarry Smith DMClone(dm, §iondm); 2259a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2260a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2261a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2262a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2263a1cb98faSBarry Smith PetscSectionSetUp(section); 2264a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2265a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2266a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2267a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2268a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2269a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2270a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2271a1cb98faSBarry Smith DMDestroy(§iondm); 2272a1cb98faSBarry Smith DMDestroy(&dm); 2273a1cb98faSBarry Smith .ve 22743e97647fSksagiyam 22751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22763e97647fSksagiyam @*/ 2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2278d71ae5a4SJacob Faibussowitsch { 22793e97647fSksagiyam PetscBool ishdf5; 22803e97647fSksagiyam 22813e97647fSksagiyam PetscFunctionBegin; 22823e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22833e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22843e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22853e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22863e97647fSksagiyam /* Check consistency */ 22873e97647fSksagiyam { 22883e97647fSksagiyam PetscSection section; 22893e97647fSksagiyam PetscBool includesConstraints; 22903e97647fSksagiyam PetscInt m, m1; 22913e97647fSksagiyam 22929566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22939566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22959566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22969566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 229763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 22983e97647fSksagiyam } 22999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23013e97647fSksagiyam if (ishdf5) { 23023e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23039566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23043e97647fSksagiyam #else 23053e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23063e97647fSksagiyam #endif 23073e97647fSksagiyam } 23089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23103e97647fSksagiyam } 23113e97647fSksagiyam 2312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2313d71ae5a4SJacob Faibussowitsch { 2314d4f5a9a0SVaclav Hapla PetscBool ishdf5; 23152c40f234SMatthew G. Knepley 23162c40f234SMatthew G. Knepley PetscFunctionBegin; 23172c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23182c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2320d4f5a9a0SVaclav Hapla if (ishdf5) { 23212c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23229c48423bSVaclav Hapla PetscViewerFormat format; 23239566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23249c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23259566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2326509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23279566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 232898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23302c40f234SMatthew G. Knepley #else 23312c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2332552f7358SJed Brown #endif 233398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2334552f7358SJed Brown } 2335552f7358SJed Brown 2336ea8e1828Sksagiyam /*@ 2337a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2338ea8e1828Sksagiyam 233920f4b53cSBarry Smith Collective 2340ea8e1828Sksagiyam 2341ea8e1828Sksagiyam Input Parameters: 2342a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2343a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2344ea8e1828Sksagiyam 23452fe279fdSBarry Smith Output Parameter: 234620f4b53cSBarry 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 2347dec9e869Sksagiyam 2348ea8e1828Sksagiyam Level: advanced 2349ea8e1828Sksagiyam 23501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2351a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2352ea8e1828Sksagiyam @*/ 2353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2354d71ae5a4SJacob Faibussowitsch { 2355ea8e1828Sksagiyam PetscBool ishdf5; 2356ea8e1828Sksagiyam 2357ea8e1828Sksagiyam PetscFunctionBegin; 2358ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2359ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23604f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2363ea8e1828Sksagiyam if (ishdf5) { 2364ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2365ea8e1828Sksagiyam PetscViewerFormat format; 23669566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2367ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23689566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 236998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2370ea8e1828Sksagiyam #else 2371ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2372ea8e1828Sksagiyam #endif 2373ea8e1828Sksagiyam } 23749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2376ea8e1828Sksagiyam } 2377ea8e1828Sksagiyam 23783e701f1cSksagiyam /*@ 2379a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23803e701f1cSksagiyam 238120f4b53cSBarry Smith Collective 23823e701f1cSksagiyam 23833e701f1cSksagiyam Input Parameters: 2384a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2385a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2386a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23873e701f1cSksagiyam 23883e701f1cSksagiyam Level: advanced 23893e701f1cSksagiyam 23901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2391a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23923e701f1cSksagiyam @*/ 2393d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2394d71ae5a4SJacob Faibussowitsch { 23953e701f1cSksagiyam PetscBool ishdf5; 23963e701f1cSksagiyam 23973e701f1cSksagiyam PetscFunctionBegin; 23983e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23993e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2400c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24033e701f1cSksagiyam if (ishdf5) { 24043e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 24053e701f1cSksagiyam PetscViewerFormat format; 24069566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24073e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24089566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 240998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24103e701f1cSksagiyam #else 24113e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24123e701f1cSksagiyam #endif 24133e701f1cSksagiyam } 24149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24163e701f1cSksagiyam } 24173e701f1cSksagiyam 2418b08ad5deSksagiyam /*@ 2419a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2420b08ad5deSksagiyam 242120f4b53cSBarry Smith Collective 2422b08ad5deSksagiyam 2423b08ad5deSksagiyam Input Parameters: 2424a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2425a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 242620f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2427b08ad5deSksagiyam 2428b08ad5deSksagiyam Level: advanced 2429b08ad5deSksagiyam 2430a1cb98faSBarry Smith Note: 2431a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2432e6368b79SVaclav Hapla 24331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2434a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2435b08ad5deSksagiyam @*/ 2436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2437d71ae5a4SJacob Faibussowitsch { 2438b08ad5deSksagiyam PetscBool ishdf5; 2439b08ad5deSksagiyam 2440b08ad5deSksagiyam PetscFunctionBegin; 2441b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2442b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2443e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2446b08ad5deSksagiyam if (ishdf5) { 2447b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2448b08ad5deSksagiyam PetscViewerFormat format; 2449b08ad5deSksagiyam 24509566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2451b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24529566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 245398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2454b08ad5deSksagiyam #else 2455b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2456b08ad5deSksagiyam #endif 2457b08ad5deSksagiyam } 24589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2460b08ad5deSksagiyam } 2461b08ad5deSksagiyam 2462f84dd6b4Sksagiyam /*@ 2463a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2464f84dd6b4Sksagiyam 246520f4b53cSBarry Smith Collective 2466f84dd6b4Sksagiyam 2467f84dd6b4Sksagiyam Input Parameters: 2468a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2469a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 2470a1cb98faSBarry Smith . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated 2471a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2472f84dd6b4Sksagiyam 2473a4e35b19SJacob Faibussowitsch Output Parameters: 247420f4b53cSBarry 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) 247520f4b53cSBarry 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) 2476f84dd6b4Sksagiyam 2477f84dd6b4Sksagiyam Level: advanced 2478f84dd6b4Sksagiyam 2479f84dd6b4Sksagiyam Notes: 248020f4b53cSBarry 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. 2481f84dd6b4Sksagiyam 248220f4b53cSBarry 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. 2483f84dd6b4Sksagiyam 248420f4b53cSBarry 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. 2485f84dd6b4Sksagiyam 2486f84dd6b4Sksagiyam Example using 2 processes: 2487a1cb98faSBarry Smith .vb 2488a1cb98faSBarry Smith NX (number of points on dm): 4 2489a1cb98faSBarry Smith sectionA : the on-disk section 2490a1cb98faSBarry Smith vecA : a vector associated with sectionA 2491a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2492a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2493a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2494f84dd6b4Sksagiyam 2495a1cb98faSBarry Smith rank 0 rank 1 2496a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2497a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2498a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2499a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2500a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2501a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2502a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2503a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2504a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2505a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2506a1cb98faSBarry Smith .ve 2507a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2508a1cb98faSBarry Smith 25091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2510f84dd6b4Sksagiyam @*/ 2511d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2512d71ae5a4SJacob Faibussowitsch { 2513f84dd6b4Sksagiyam PetscBool ishdf5; 2514f84dd6b4Sksagiyam 2515f84dd6b4Sksagiyam PetscFunctionBegin; 2516f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2517f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2518f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2519f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25204f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25214f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2524f84dd6b4Sksagiyam if (ishdf5) { 2525f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25269566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2527f84dd6b4Sksagiyam #else 2528f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2529f84dd6b4Sksagiyam #endif 2530f84dd6b4Sksagiyam } 25319566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2533f84dd6b4Sksagiyam } 2534f84dd6b4Sksagiyam 25358be3dfe1Sksagiyam /*@ 25368be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25378be3dfe1Sksagiyam 253820f4b53cSBarry Smith Collective 25398be3dfe1Sksagiyam 25408be3dfe1Sksagiyam Input Parameters: 2541a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2542a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2543a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 2544a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25458be3dfe1Sksagiyam - vec - The global vector to set values of 25468be3dfe1Sksagiyam 25478be3dfe1Sksagiyam Level: advanced 25488be3dfe1Sksagiyam 25498be3dfe1Sksagiyam Notes: 2550a1cb98faSBarry 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. 25518be3dfe1Sksagiyam 255260225df5SJacob Faibussowitsch Calling sequence: 2553a1cb98faSBarry Smith .vb 2554a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2555a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2556a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2557a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2558a1cb98faSBarry Smith DMClone(dm, §iondm); 2559a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2560a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2561a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2562a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2563a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2564a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2565a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2566a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2567a1cb98faSBarry Smith DMDestroy(§iondm); 2568a1cb98faSBarry Smith DMDestroy(&dm); 2569a1cb98faSBarry Smith .ve 25708be3dfe1Sksagiyam 25711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2572a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25738be3dfe1Sksagiyam @*/ 2574d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2575d71ae5a4SJacob Faibussowitsch { 25768be3dfe1Sksagiyam PetscBool ishdf5; 25778be3dfe1Sksagiyam 25788be3dfe1Sksagiyam PetscFunctionBegin; 25798be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25808be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25818be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25828be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25838be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25848be3dfe1Sksagiyam /* Check consistency */ 25858be3dfe1Sksagiyam { 25868be3dfe1Sksagiyam PetscSection section; 25878be3dfe1Sksagiyam PetscBool includesConstraints; 25888be3dfe1Sksagiyam PetscInt m, m1; 25898be3dfe1Sksagiyam 25909566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25919566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25939566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25949566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 259563a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 25968be3dfe1Sksagiyam } 25979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25989566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 25998be3dfe1Sksagiyam if (ishdf5) { 26008be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26019566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26028be3dfe1Sksagiyam #else 26038be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26048be3dfe1Sksagiyam #endif 26058be3dfe1Sksagiyam } 26069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26088be3dfe1Sksagiyam } 26098be3dfe1Sksagiyam 26108be3dfe1Sksagiyam /*@ 26118be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 26128be3dfe1Sksagiyam 261320f4b53cSBarry Smith Collective 26148be3dfe1Sksagiyam 26158be3dfe1Sksagiyam Input Parameters: 2616a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2617a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2618a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined 2619a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26208be3dfe1Sksagiyam - vec - The local vector to set values of 26218be3dfe1Sksagiyam 26228be3dfe1Sksagiyam Level: advanced 26238be3dfe1Sksagiyam 26248be3dfe1Sksagiyam Notes: 262520f4b53cSBarry 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. 26268be3dfe1Sksagiyam 262760225df5SJacob Faibussowitsch Calling sequence: 2628a1cb98faSBarry Smith .vb 2629a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2630a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2631a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2632a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2633a1cb98faSBarry Smith DMClone(dm, §iondm); 2634a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2635a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2636a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2637a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2638a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2639a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2640a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2641a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2642a1cb98faSBarry Smith DMDestroy(§iondm); 2643a1cb98faSBarry Smith DMDestroy(&dm); 2644a1cb98faSBarry Smith .ve 26458be3dfe1Sksagiyam 26461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2647a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26488be3dfe1Sksagiyam @*/ 2649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2650d71ae5a4SJacob Faibussowitsch { 26518be3dfe1Sksagiyam PetscBool ishdf5; 26528be3dfe1Sksagiyam 26538be3dfe1Sksagiyam PetscFunctionBegin; 26548be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26558be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26568be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26578be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26588be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26598be3dfe1Sksagiyam /* Check consistency */ 26608be3dfe1Sksagiyam { 26618be3dfe1Sksagiyam PetscSection section; 26628be3dfe1Sksagiyam PetscBool includesConstraints; 26638be3dfe1Sksagiyam PetscInt m, m1; 26648be3dfe1Sksagiyam 26659566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26669566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26689566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26699566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 267063a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26718be3dfe1Sksagiyam } 26729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26739566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26748be3dfe1Sksagiyam if (ishdf5) { 26758be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26769566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26778be3dfe1Sksagiyam #else 26788be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26798be3dfe1Sksagiyam #endif 26808be3dfe1Sksagiyam } 26819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26838be3dfe1Sksagiyam } 26848be3dfe1Sksagiyam 2685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2686d71ae5a4SJacob Faibussowitsch { 2687552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2688552f7358SJed Brown 2689552f7358SJed Brown PetscFunctionBegin; 26909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26946c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 26952e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 26962e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 26972e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 26982e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 26996bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 27006bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2701d02c7345SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSectionGetDefault_C", NULL)); 2702d02c7345SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSectionSetDefault_C", NULL)); 2703c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2704c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2705d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2706d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 27075f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 27083ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 27099566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 27109566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 27119566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 27129566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 27139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 27149566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 271521027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27169f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27189566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27199566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27201d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27219566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27229566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27264e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27276725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27286725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27299566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27319566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27329566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27339566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27349566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27359566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27379566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27389566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27399566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2740552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27419566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2743552f7358SJed Brown } 2744552f7358SJed Brown 2745d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2746d71ae5a4SJacob Faibussowitsch { 2747d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2748acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27499fca9976SJed Brown PetscInt localSize, localStart = 0; 2750837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2751b412c318SBarry Smith MatType mtype; 27521428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2753552f7358SJed Brown 2754552f7358SJed Brown PetscFunctionBegin; 27559566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2756b412c318SBarry Smith mtype = dm->mattype; 2757d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 27589566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27599566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27619fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27629566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27639566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27649566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27659566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27669566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2767acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27689566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27699566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27709566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27719566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27739566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2776552f7358SJed Brown if (!isShell) { 2777837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27789fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2779863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2780552f7358SJed Brown 27819566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27829fca9976SJed Brown 27839fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2785863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2786e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2787863027abSJed Brown switch (dm->blocking_type) { 27880e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27899fca9976SJed Brown PetscInt bdof, offset; 2790a9d99c84SMatthew G. Knepley 27919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27929fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 27939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 2794d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2795d02c7345SMatthew G. Knepley // Signal block concatenation 2796d02c7345SMatthew G. Knepley if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof); 27971d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 27981d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 27991d17a0a3SMatthew G. Knepley if (dof) { 28009371c9d4SSatish Balay if (bs < 0) { 28019371c9d4SSatish Balay bs = bdof; 28029371c9d4SSatish Balay } else if (bs != bdof) { 28039371c9d4SSatish Balay bs = 1; 28049371c9d4SSatish Balay } 2805552f7358SJed Brown } 2806863027abSJed Brown } break; 2807863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2808863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2809863027abSJed Brown PetscInt num_comp, bdof, offset; 2810863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2811863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2812863027abSJed Brown if (dof < 0) continue; 2813863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2814863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2815863027abSJed 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); 2816863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2817863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2818863027abSJed Brown // Handle possibly constant block size (unlikely) 2819863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2820863027abSJed Brown if (dof) { 2821863027abSJed Brown if (bs < 0) { 2822863027abSJed Brown bs = bdof; 2823863027abSJed Brown } else if (bs != bdof) { 2824863027abSJed Brown bs = 1; 2825863027abSJed Brown } 2826863027abSJed Brown } 2827863027abSJed Brown } 2828863027abSJed Brown } break; 2829863027abSJed Brown } 28302a28c762SMatthew G Knepley } 28312a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2832e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2833e432b41dSStefano Zampini bsLocal[1] = bs; 28349566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2835e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2836e432b41dSStefano Zampini else bs = bsMinMax[0]; 28376fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28389566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28390682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28409566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28419566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28420682b8bbSJed Brown } else { 28439566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28449566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28459566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2846552f7358SJed Brown } 28479fca9976SJed Brown { // Consolidate blocks 28489fca9976SJed Brown PetscInt nblocks = 0; 28499fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28509fca9976SJed Brown if (pblocks[i] == 0) continue; 2851d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2852d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2853d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2854d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2855d02c7345SMatthew G. Knepley } else { 28569fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2857d02c7345SMatthew G. Knepley } 2858ad540459SPierre 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]); 28599fca9976SJed Brown } 28609fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28619fca9976SJed Brown } 28629fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2863aa0f6e3cSJed Brown } 28649566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2866552f7358SJed Brown } 2867552f7358SJed Brown 28687cd05799SMatthew G. Knepley /*@ 2869a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2870be36d101SStefano Zampini 2871a1cb98faSBarry Smith Not Collective 2872be36d101SStefano Zampini 2873be36d101SStefano Zampini Input Parameter: 287460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2875be36d101SStefano Zampini 28762fe279fdSBarry Smith Output Parameter: 2877be36d101SStefano Zampini . subsection - The subdomain section 2878be36d101SStefano Zampini 2879be36d101SStefano Zampini Level: developer 2880be36d101SStefano Zampini 28811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28827cd05799SMatthew G. Knepley @*/ 2883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2884d71ae5a4SJacob Faibussowitsch { 2885be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2886be36d101SStefano Zampini 2887be36d101SStefano Zampini PetscFunctionBegin; 2888be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2889be36d101SStefano Zampini if (!mesh->subdomainSection) { 2890be36d101SStefano Zampini PetscSection section; 2891be36d101SStefano Zampini PetscSF sf; 2892be36d101SStefano Zampini 28939566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 28949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 28959566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 28969566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2897be36d101SStefano Zampini } 2898be36d101SStefano Zampini *subsection = mesh->subdomainSection; 28993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2900be36d101SStefano Zampini } 2901be36d101SStefano Zampini 2902552f7358SJed Brown /*@ 290320f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2904552f7358SJed Brown 2905a1cb98faSBarry Smith Not Collective 2906552f7358SJed Brown 2907552f7358SJed Brown Input Parameter: 290860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2909552f7358SJed Brown 2910552f7358SJed Brown Output Parameters: 2911552f7358SJed Brown + pStart - The first mesh point 2912552f7358SJed Brown - pEnd - The upper bound for mesh points 2913552f7358SJed Brown 2914552f7358SJed Brown Level: beginner 2915552f7358SJed Brown 29161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2917552f7358SJed Brown @*/ 2918d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2919d71ae5a4SJacob Faibussowitsch { 2920552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2921552f7358SJed Brown 2922552f7358SJed Brown PetscFunctionBegin; 2923552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29249f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 29259f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 29263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2927552f7358SJed Brown } 2928552f7358SJed Brown 2929552f7358SJed Brown /*@ 293020f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2931552f7358SJed Brown 2932a1cb98faSBarry Smith Not Collective 2933552f7358SJed Brown 2934552f7358SJed Brown Input Parameters: 293560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2936552f7358SJed Brown . pStart - The first mesh point 2937552f7358SJed Brown - pEnd - The upper bound for mesh points 2938552f7358SJed Brown 2939552f7358SJed Brown Level: beginner 2940552f7358SJed Brown 29411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2942552f7358SJed Brown @*/ 2943d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2944d71ae5a4SJacob Faibussowitsch { 2945552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2946552f7358SJed Brown 2947552f7358SJed Brown PetscFunctionBegin; 2948552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 295121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2953552f7358SJed Brown } 2954552f7358SJed Brown 2955552f7358SJed Brown /*@ 2956eaf898f9SPatrick Sanan DMPlexGetConeSize - Return 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()` 2963552f7358SJed Brown 2964552f7358SJed Brown Output Parameter: 296520f4b53cSBarry Smith . size - The cone size for point `p` 2966552f7358SJed Brown 2967552f7358SJed Brown Level: beginner 2968552f7358SJed Brown 29691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2970552f7358SJed Brown @*/ 2971d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2972d71ae5a4SJacob Faibussowitsch { 2973552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2974552f7358SJed Brown 2975552f7358SJed Brown PetscFunctionBegin; 2976552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29774f572ea9SToby Isaac PetscAssertPointer(size, 3); 29789f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29799f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2981552f7358SJed Brown } 2982552f7358SJed Brown 2983552f7358SJed Brown /*@ 2984eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2985552f7358SJed Brown 2986a1cb98faSBarry Smith Not Collective 2987552f7358SJed Brown 2988552f7358SJed Brown Input Parameters: 298960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2990a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 299120f4b53cSBarry Smith - size - The cone size for point `p` 2992552f7358SJed Brown 2993552f7358SJed Brown Level: beginner 2994552f7358SJed Brown 2995a1cb98faSBarry Smith Note: 2996a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 2997a1cb98faSBarry Smith 29981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2999552f7358SJed Brown @*/ 3000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3001d71ae5a4SJacob Faibussowitsch { 3002552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3003552f7358SJed Brown 3004552f7358SJed Brown PetscFunctionBegin; 3005552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30069f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3009552f7358SJed Brown } 3010552f7358SJed Brown 3011552f7358SJed Brown /*@C 3012eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3013552f7358SJed Brown 3014a1cb98faSBarry Smith Not Collective 3015552f7358SJed Brown 3016552f7358SJed Brown Input Parameters: 3017a1cb98faSBarry Smith + dm - The `DMPLEX` 3018a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3019552f7358SJed Brown 3020552f7358SJed Brown Output Parameter: 302120f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 3022552f7358SJed Brown 3023552f7358SJed Brown Level: beginner 3024552f7358SJed Brown 302560225df5SJacob Faibussowitsch Fortran Notes: 3026a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3027a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30283813dfbdSMatthew G Knepley 30291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3030552f7358SJed Brown @*/ 3031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3032d71ae5a4SJacob Faibussowitsch { 3033552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3034552f7358SJed Brown PetscInt off; 3035552f7358SJed Brown 3036552f7358SJed Brown PetscFunctionBegin; 3037552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30384f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30408e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 30413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3042552f7358SJed Brown } 3043552f7358SJed Brown 30440ce7577fSVaclav Hapla /*@C 30450ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30460ce7577fSVaclav Hapla 3047a1cb98faSBarry Smith Not Collective 30480ce7577fSVaclav Hapla 30490ce7577fSVaclav Hapla Input Parameters: 3050a1cb98faSBarry Smith + dm - The `DMPLEX` 3051a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30520ce7577fSVaclav Hapla 3053d8d19677SJose E. Roman Output Parameters: 305420f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 305520f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30560ce7577fSVaclav Hapla 30570ce7577fSVaclav Hapla Level: intermediate 30580ce7577fSVaclav Hapla 30591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30600ce7577fSVaclav Hapla @*/ 3061d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3062d71ae5a4SJacob Faibussowitsch { 30630ce7577fSVaclav Hapla PetscSection cs, newcs; 30640ce7577fSVaclav Hapla PetscInt *cones; 30650ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30660ce7577fSVaclav Hapla PetscInt n; 30670ce7577fSVaclav Hapla 30680ce7577fSVaclav Hapla PetscFunctionBegin; 30699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30719566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30720ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30730ce7577fSVaclav Hapla if (pCones) { 30749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30759566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30760ce7577fSVaclav Hapla } 30773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30780ce7577fSVaclav Hapla } 30790ce7577fSVaclav Hapla 3080af9eab45SVaclav Hapla /*@ 3081af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3082d4636a37SVaclav Hapla 3083a1cb98faSBarry Smith Not Collective 3084d4636a37SVaclav Hapla 3085d4636a37SVaclav Hapla Input Parameters: 3086a1cb98faSBarry Smith + dm - The `DMPLEX` 3087a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3088d4636a37SVaclav Hapla 3089d4636a37SVaclav Hapla Output Parameter: 3090af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3091d4636a37SVaclav Hapla 3092d4636a37SVaclav Hapla Level: advanced 3093d4636a37SVaclav Hapla 3094af9eab45SVaclav Hapla Notes: 309520f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3096af9eab45SVaclav Hapla 3097a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3098a1cb98faSBarry Smith 30991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3100a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3101d4636a37SVaclav Hapla @*/ 3102d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3103d71ae5a4SJacob Faibussowitsch { 3104af9eab45SVaclav Hapla IS *expandedPointsAll; 3105af9eab45SVaclav Hapla PetscInt depth; 3106d4636a37SVaclav Hapla 3107d4636a37SVaclav Hapla PetscFunctionBegin; 3108af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3109af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31104f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 31119566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3112af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 31139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 31149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 31153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3116af9eab45SVaclav Hapla } 3117af9eab45SVaclav Hapla 3118af9eab45SVaclav Hapla /*@ 3119af9eab45SVaclav 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). 3120af9eab45SVaclav Hapla 3121a1cb98faSBarry Smith Not Collective 3122af9eab45SVaclav Hapla 3123af9eab45SVaclav Hapla Input Parameters: 3124a1cb98faSBarry Smith + dm - The `DMPLEX` 3125a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3126af9eab45SVaclav Hapla 3127d8d19677SJose E. Roman Output Parameters: 3128a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3129af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3130af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3131af9eab45SVaclav Hapla 3132af9eab45SVaclav Hapla Level: advanced 3133af9eab45SVaclav Hapla 3134af9eab45SVaclav Hapla Notes: 3135a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3136af9eab45SVaclav Hapla 3137a4e35b19SJacob 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. 3138af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3139af9eab45SVaclav Hapla 3140a4e35b19SJacob 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\: 3141a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3142a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3143af9eab45SVaclav Hapla 31441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3145a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3146af9eab45SVaclav Hapla @*/ 3147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3148d71ae5a4SJacob Faibussowitsch { 3149af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3150af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3151af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3152af9eab45SVaclav Hapla IS *expandedPoints_; 3153af9eab45SVaclav Hapla PetscSection *sections_; 3154af9eab45SVaclav Hapla 3155af9eab45SVaclav Hapla PetscFunctionBegin; 3156af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3157af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31584f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31594f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31604f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3166af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3167af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31689566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3170af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3172af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3175af9eab45SVaclav Hapla } else { 31769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3177af9eab45SVaclav Hapla } 3178af9eab45SVaclav Hapla } 31799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3182af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3185af9eab45SVaclav Hapla if (cn > 1) { 31869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31879566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3188af9eab45SVaclav Hapla } else { 3189af9eab45SVaclav Hapla newarr[co] = arr[i]; 3190af9eab45SVaclav Hapla } 3191af9eab45SVaclav Hapla } 31929566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3193af9eab45SVaclav Hapla arr = newarr; 3194af9eab45SVaclav Hapla n = newn; 3195af9eab45SVaclav Hapla } 31969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3197af9eab45SVaclav Hapla *depth = depth_; 3198af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3199af9eab45SVaclav Hapla else { 32009566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32019566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3202af9eab45SVaclav Hapla } 3203af9eab45SVaclav Hapla if (sections) *sections = sections_; 3204af9eab45SVaclav Hapla else { 32059566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32069566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3207af9eab45SVaclav Hapla } 32083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3209af9eab45SVaclav Hapla } 3210af9eab45SVaclav Hapla 3211af9eab45SVaclav Hapla /*@ 3212a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3213af9eab45SVaclav Hapla 3214a1cb98faSBarry Smith Not Collective 3215af9eab45SVaclav Hapla 3216af9eab45SVaclav Hapla Input Parameters: 3217a1cb98faSBarry Smith + dm - The `DMPLEX` 3218a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3219af9eab45SVaclav Hapla 3220d8d19677SJose E. Roman Output Parameters: 3221a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3222af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3223af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3224af9eab45SVaclav Hapla 3225af9eab45SVaclav Hapla Level: advanced 3226af9eab45SVaclav Hapla 3227a1cb98faSBarry Smith Note: 3228a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3229af9eab45SVaclav Hapla 32301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3231a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3232af9eab45SVaclav Hapla @*/ 3233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3234d71ae5a4SJacob Faibussowitsch { 3235af9eab45SVaclav Hapla PetscInt d, depth_; 3236af9eab45SVaclav Hapla 3237af9eab45SVaclav Hapla PetscFunctionBegin; 32389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32391dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3240af9eab45SVaclav Hapla if (depth) *depth = 0; 3241af9eab45SVaclav Hapla if (expandedPoints) { 32429566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32439566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3244af9eab45SVaclav Hapla } 3245af9eab45SVaclav Hapla if (sections) { 32469566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32479566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3248af9eab45SVaclav Hapla } 32493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3250d4636a37SVaclav Hapla } 3251d4636a37SVaclav Hapla 3252552f7358SJed Brown /*@ 325392371b87SBarry 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 3254552f7358SJed Brown 3255a1cb98faSBarry Smith Not Collective 3256552f7358SJed Brown 3257552f7358SJed Brown Input Parameters: 325860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3259a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 326020f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3261552f7358SJed Brown 3262552f7358SJed Brown Level: beginner 3263552f7358SJed Brown 3264a1cb98faSBarry Smith Note: 3265a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3266a1cb98faSBarry Smith 32671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3268552f7358SJed Brown @*/ 3269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3270d71ae5a4SJacob Faibussowitsch { 3271552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3272552f7358SJed Brown PetscInt dof, off, c; 3273552f7358SJed Brown 3274552f7358SJed Brown PetscFunctionBegin; 3275552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32774f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3279db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3280db485b19SStefano Zampini PetscInt pStart, pEnd; 3281db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 328263a3b9bcSJacob 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); 3283552f7358SJed Brown for (c = 0; c < dof; ++c) { 328463a3b9bcSJacob 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); 3285552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3286552f7358SJed Brown } 3287db485b19SStefano Zampini } else { 3288db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3289db485b19SStefano Zampini } 32903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3291552f7358SJed Brown } 3292552f7358SJed Brown 3293552f7358SJed Brown /*@C 3294eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3295552f7358SJed Brown 3296a1cb98faSBarry Smith Not Collective 3297552f7358SJed Brown 3298552f7358SJed Brown Input Parameters: 329960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3300a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3301552f7358SJed Brown 3302552f7358SJed Brown Output Parameter: 330320f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3304b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3305552f7358SJed Brown 3306552f7358SJed Brown Level: beginner 3307552f7358SJed Brown 3308a1cb98faSBarry Smith Note: 3309b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3310b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3311a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3312b5a892a1SMatthew G. Knepley with the identity. 3313b5a892a1SMatthew G. Knepley 331460225df5SJacob Faibussowitsch Fortran Notes: 3315a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3316a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 33173813dfbdSMatthew G Knepley 33181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3319552f7358SJed Brown @*/ 3320d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3321d71ae5a4SJacob Faibussowitsch { 3322552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3323552f7358SJed Brown PetscInt off; 3324552f7358SJed Brown 3325552f7358SJed Brown PetscFunctionBegin; 3326552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 332776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3328552f7358SJed Brown PetscInt dof; 33299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33304f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3331552f7358SJed Brown } 33329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33330d644c17SKarl Rupp 3334552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3336552f7358SJed Brown } 3337552f7358SJed Brown 3338552f7358SJed Brown /*@ 3339eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3340552f7358SJed Brown 3341a1cb98faSBarry Smith Not Collective 3342552f7358SJed Brown 3343552f7358SJed Brown Input Parameters: 334460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3345a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3346b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3347b5a892a1SMatthew G. Knepley 3348552f7358SJed Brown Level: beginner 3349552f7358SJed Brown 3350a1cb98faSBarry Smith Notes: 3351a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3352a1cb98faSBarry Smith 3353a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3354a1cb98faSBarry Smith 33551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3356552f7358SJed Brown @*/ 3357d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3358d71ae5a4SJacob Faibussowitsch { 3359552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3360552f7358SJed Brown PetscInt pStart, pEnd; 3361552f7358SJed Brown PetscInt dof, off, c; 3362552f7358SJed Brown 3363552f7358SJed Brown PetscFunctionBegin; 3364552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33664f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3368db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3369db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 337063a3b9bcSJacob 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); 3371552f7358SJed Brown for (c = 0; c < dof; ++c) { 3372552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3373552f7358SJed Brown 33749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33751dca8a05SBarry 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); 3376552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3377552f7358SJed Brown } 3378db485b19SStefano Zampini } else { 3379db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3380db485b19SStefano Zampini } 33813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3382552f7358SJed Brown } 3383552f7358SJed Brown 33847cd05799SMatthew G. Knepley /*@ 3385eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33867cd05799SMatthew G. Knepley 3387a1cb98faSBarry Smith Not Collective 33887cd05799SMatthew G. Knepley 33897cd05799SMatthew G. Knepley Input Parameters: 339060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3391a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33927cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 33937cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 33947cd05799SMatthew G. Knepley 33957cd05799SMatthew G. Knepley Level: beginner 33967cd05799SMatthew G. Knepley 33971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33987cd05799SMatthew G. Knepley @*/ 3399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3400d71ae5a4SJacob Faibussowitsch { 3401552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3402552f7358SJed Brown PetscInt pStart, pEnd; 3403552f7358SJed Brown PetscInt dof, off; 3404552f7358SJed Brown 3405552f7358SJed Brown PetscFunctionBegin; 3406552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3407a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 340963a3b9bcSJacob 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); 341063a3b9bcSJacob 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); 34119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 341263a3b9bcSJacob 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); 3413a03d55ffSStefano Zampini } 3414a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3415552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 34163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3417552f7358SJed Brown } 3418552f7358SJed Brown 34197cd05799SMatthew G. Knepley /*@ 3420eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 34217cd05799SMatthew G. Knepley 3422a1cb98faSBarry Smith Not Collective 34237cd05799SMatthew G. Knepley 34247cd05799SMatthew G. Knepley Input Parameters: 342560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3426a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34277cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34287cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34297cd05799SMatthew G. Knepley 34307cd05799SMatthew G. Knepley Level: beginner 34317cd05799SMatthew G. Knepley 3432a1cb98faSBarry Smith Note: 3433a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3434b5a892a1SMatthew G. Knepley 34351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34367cd05799SMatthew G. Knepley @*/ 3437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3438d71ae5a4SJacob Faibussowitsch { 343977c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 344077c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 344177c88f5bSMatthew G Knepley PetscInt dof, off; 344277c88f5bSMatthew G Knepley 344377c88f5bSMatthew G Knepley PetscFunctionBegin; 344477c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3445a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 344763a3b9bcSJacob 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); 34489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 344963a3b9bcSJacob 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); 3450a03d55ffSStefano Zampini } 3451a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 345277c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 345477c88f5bSMatthew G Knepley } 345577c88f5bSMatthew G Knepley 34569f4ada15SMatthew G. Knepley /*@C 34579f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34589f4ada15SMatthew G. Knepley 34599f4ada15SMatthew G. Knepley Not collective 34609f4ada15SMatthew G. Knepley 34619f4ada15SMatthew G. Knepley Input Parameters: 34629f4ada15SMatthew G. Knepley + dm - The DMPlex 34639f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34649f4ada15SMatthew G. Knepley 34659f4ada15SMatthew G. Knepley Output Parameters: 346620f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 346720f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34689f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34699f4ada15SMatthew G. Knepley 34709f4ada15SMatthew G. Knepley Level: beginner 34719f4ada15SMatthew G. Knepley 34729f4ada15SMatthew G. Knepley Notes: 34739f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34749f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 347520f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34769f4ada15SMatthew G. Knepley with the identity. 34779f4ada15SMatthew G. Knepley 34789f4ada15SMatthew G. Knepley Fortran Notes: 347920f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 348020f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34819f4ada15SMatthew G. Knepley 34821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34839f4ada15SMatthew G. Knepley @*/ 34849f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34859f4ada15SMatthew G. Knepley { 34869f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34879f4ada15SMatthew G. Knepley 34889f4ada15SMatthew G. Knepley PetscFunctionBegin; 34899f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34909f4ada15SMatthew G. Knepley if (mesh->tr) { 34919f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34929f4ada15SMatthew G. Knepley } else { 34939f4ada15SMatthew G. Knepley PetscInt off; 34949f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 34959f4ada15SMatthew G. Knepley PetscInt dof; 34969f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34979f4ada15SMatthew G. Knepley if (dof) { 34984f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 34994f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35009f4ada15SMatthew G. Knepley } 35019f4ada15SMatthew G. Knepley } 35029f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35038e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 35048e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 35059f4ada15SMatthew G. Knepley } 35063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35079f4ada15SMatthew G. Knepley } 35089f4ada15SMatthew G. Knepley 35099f4ada15SMatthew G. Knepley /*@C 35109f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 35119f4ada15SMatthew G. Knepley 351220f4b53cSBarry Smith Not Collective 35139f4ada15SMatthew G. Knepley 35149f4ada15SMatthew G. Knepley Input Parameters: 35159f4ada15SMatthew G. Knepley + dm - The DMPlex 351620f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35179f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 351820f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35199f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35209f4ada15SMatthew G. Knepley 35219f4ada15SMatthew G. Knepley Level: beginner 35229f4ada15SMatthew G. Knepley 35239f4ada15SMatthew G. Knepley Notes: 35249f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35259f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 352620f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35279f4ada15SMatthew G. Knepley with the identity. 35289f4ada15SMatthew G. Knepley 352960225df5SJacob Faibussowitsch Fortran Notes: 353020f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 353120f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35329f4ada15SMatthew G. Knepley 35331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35349f4ada15SMatthew G. Knepley @*/ 35359f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35369f4ada15SMatthew G. Knepley { 35379f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35389f4ada15SMatthew G. Knepley 35399f4ada15SMatthew G. Knepley PetscFunctionBegin; 35409f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35419f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35439f4ada15SMatthew G. Knepley } 35449f4ada15SMatthew G. Knepley 3545552f7358SJed Brown /*@ 3546eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3547552f7358SJed Brown 3548a1cb98faSBarry Smith Not Collective 3549552f7358SJed Brown 3550552f7358SJed Brown Input Parameters: 355160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3552a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3553552f7358SJed Brown 3554552f7358SJed Brown Output Parameter: 355520f4b53cSBarry Smith . size - The support size for point `p` 3556552f7358SJed Brown 3557552f7358SJed Brown Level: beginner 3558552f7358SJed Brown 35591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3560552f7358SJed Brown @*/ 3561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(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); 35674f572ea9SToby Isaac PetscAssertPointer(size, 3); 35689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3570552f7358SJed Brown } 3571552f7358SJed Brown 3572552f7358SJed Brown /*@ 3573eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3574552f7358SJed Brown 3575a1cb98faSBarry Smith Not Collective 3576552f7358SJed Brown 3577552f7358SJed Brown Input Parameters: 357860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3579a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 358020f4b53cSBarry Smith - size - The support size for point `p` 3581552f7358SJed Brown 3582a1cb98faSBarry Smith Level: beginner 3583552f7358SJed Brown 3584552f7358SJed Brown Note: 358520f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3586552f7358SJed Brown 35871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3588552f7358SJed Brown @*/ 3589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3590d71ae5a4SJacob Faibussowitsch { 3591552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3592552f7358SJed Brown 3593552f7358SJed Brown PetscFunctionBegin; 3594552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 35963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3597552f7358SJed Brown } 3598552f7358SJed Brown 3599552f7358SJed Brown /*@C 3600eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3601552f7358SJed Brown 3602a1cb98faSBarry Smith Not Collective 3603552f7358SJed Brown 3604552f7358SJed Brown Input Parameters: 360560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3606a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3607552f7358SJed Brown 3608552f7358SJed Brown Output Parameter: 360920f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3610552f7358SJed Brown 3611552f7358SJed Brown Level: beginner 3612552f7358SJed Brown 361360225df5SJacob Faibussowitsch Fortran Notes: 3614a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3615a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 36163813dfbdSMatthew G Knepley 36171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3618552f7358SJed Brown @*/ 3619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3620d71ae5a4SJacob Faibussowitsch { 3621552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3622552f7358SJed Brown PetscInt off; 3623552f7358SJed Brown 3624552f7358SJed Brown PetscFunctionBegin; 3625552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36264f572ea9SToby Isaac PetscAssertPointer(support, 3); 36279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 36288e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 36293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3630552f7358SJed Brown } 3631552f7358SJed Brown 3632552f7358SJed Brown /*@ 363392371b87SBarry 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 3634552f7358SJed Brown 3635a1cb98faSBarry Smith Not Collective 3636552f7358SJed Brown 3637552f7358SJed Brown Input Parameters: 363860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3639a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 364020f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3641552f7358SJed Brown 3642552f7358SJed Brown Level: beginner 3643552f7358SJed Brown 3644a1cb98faSBarry Smith Note: 3645a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3646a1cb98faSBarry Smith 36471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3648552f7358SJed Brown @*/ 3649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3650d71ae5a4SJacob Faibussowitsch { 3651552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3652552f7358SJed Brown PetscInt pStart, pEnd; 3653552f7358SJed Brown PetscInt dof, off, c; 3654552f7358SJed Brown 3655552f7358SJed Brown PetscFunctionBegin; 3656552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36594f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 366163a3b9bcSJacob 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); 3662552f7358SJed Brown for (c = 0; c < dof; ++c) { 366363a3b9bcSJacob 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); 3664552f7358SJed Brown mesh->supports[off + c] = support[c]; 3665552f7358SJed Brown } 36663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3667552f7358SJed Brown } 3668552f7358SJed Brown 36697cd05799SMatthew G. Knepley /*@ 3670eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36717cd05799SMatthew G. Knepley 3672a1cb98faSBarry Smith Not Collective 36737cd05799SMatthew G. Knepley 36747cd05799SMatthew G. Knepley Input Parameters: 367560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3676a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36777cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36787cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36797cd05799SMatthew G. Knepley 36807cd05799SMatthew G. Knepley Level: beginner 36817cd05799SMatthew G. Knepley 36821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36837cd05799SMatthew G. Knepley @*/ 3684d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3685d71ae5a4SJacob Faibussowitsch { 3686552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3687552f7358SJed Brown PetscInt pStart, pEnd; 3688552f7358SJed Brown PetscInt dof, off; 3689552f7358SJed Brown 3690552f7358SJed Brown PetscFunctionBegin; 3691552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 369563a3b9bcSJacob 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); 369663a3b9bcSJacob 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); 369763a3b9bcSJacob 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); 3698552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 36993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3700552f7358SJed Brown } 3701552f7358SJed Brown 3702b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3703d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3704d71ae5a4SJacob Faibussowitsch { 3705b5a892a1SMatthew G. Knepley switch (ct) { 3706b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3707b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3708b5a892a1SMatthew G. Knepley break; 3709b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3710b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3711b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3712b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3713b5a892a1SMatthew G. Knepley break; 3714b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3715b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3716b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3717b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3718b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3719b5a892a1SMatthew G. Knepley break; 3720d71ae5a4SJacob Faibussowitsch default: 3721d71ae5a4SJacob Faibussowitsch return o; 3722b5a892a1SMatthew G. Knepley } 3723b5a892a1SMatthew G. Knepley return o; 3724b5a892a1SMatthew G. Knepley } 3725b5a892a1SMatthew G. Knepley 3726b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3727d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3728d71ae5a4SJacob Faibussowitsch { 3729b5a892a1SMatthew G. Knepley switch (ct) { 3730b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3731b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3732b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3733b5a892a1SMatthew G. Knepley break; 3734b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3735b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3736b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3737b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3738b5a892a1SMatthew G. Knepley break; 3739b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3740b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3741b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3742b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3743b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3744b5a892a1SMatthew G. Knepley break; 3745d71ae5a4SJacob Faibussowitsch default: 3746d71ae5a4SJacob Faibussowitsch return o; 3747b5a892a1SMatthew G. Knepley } 3748b5a892a1SMatthew G. Knepley return o; 3749b5a892a1SMatthew G. Knepley } 3750b5a892a1SMatthew G. Knepley 3751b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3752d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3753d71ae5a4SJacob Faibussowitsch { 3754b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3755b5a892a1SMatthew G. Knepley 3756b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3758b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3759b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3760b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3761b5a892a1SMatthew G. Knepley 37629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3765b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3766b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3767b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3768b5a892a1SMatthew G. Knepley 37699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3770b5a892a1SMatthew G. Knepley switch (ct) { 3771b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37729566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37739566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3774b5a892a1SMatthew G. Knepley break; 3775b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37769566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37779566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37789566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3779b5a892a1SMatthew G. Knepley break; 3780b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37819566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37829566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37839566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37849566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3785b5a892a1SMatthew G. Knepley break; 3786d71ae5a4SJacob Faibussowitsch default: 3787d71ae5a4SJacob Faibussowitsch break; 3788b5a892a1SMatthew G. Knepley } 3789b5a892a1SMatthew G. Knepley } 3790b5a892a1SMatthew G. Knepley } 37913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3792b5a892a1SMatthew G. Knepley } 3793b5a892a1SMatthew G. Knepley 379409015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 379509015e70SStefano Zampini { 379609015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 379709015e70SStefano Zampini 379809015e70SStefano Zampini PetscFunctionBeginHot; 379909015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 380009015e70SStefano Zampini if (useCone) { 380109015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 380209015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 380309015e70SStefano Zampini } else { 380409015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 380509015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 380609015e70SStefano Zampini } 380709015e70SStefano Zampini } else { 380809015e70SStefano Zampini if (useCone) { 380909015e70SStefano Zampini const PetscSection s = mesh->coneSection; 381009015e70SStefano Zampini const PetscInt ps = p - s->pStart; 381109015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 381209015e70SStefano Zampini 381309015e70SStefano Zampini *size = s->atlasDof[ps]; 381409015e70SStefano Zampini *arr = mesh->cones + off; 381509015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 381609015e70SStefano Zampini } else { 381709015e70SStefano Zampini const PetscSection s = mesh->supportSection; 381809015e70SStefano Zampini const PetscInt ps = p - s->pStart; 381909015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 382009015e70SStefano Zampini 382109015e70SStefano Zampini *size = s->atlasDof[ps]; 382209015e70SStefano Zampini *arr = mesh->supports + off; 382309015e70SStefano Zampini } 382409015e70SStefano Zampini } 382509015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 382609015e70SStefano Zampini } 382709015e70SStefano Zampini 382809015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 382909015e70SStefano Zampini { 383009015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 383109015e70SStefano Zampini 383209015e70SStefano Zampini PetscFunctionBeginHot; 383309015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 383409015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 383509015e70SStefano Zampini } 383609015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 383709015e70SStefano Zampini } 383809015e70SStefano Zampini 3839d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3840d71ae5a4SJacob Faibussowitsch { 3841b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3842b5a892a1SMatthew G. Knepley PetscInt *closure; 3843b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3844b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3845b5a892a1SMatthew G. Knepley 3846b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3847b5a892a1SMatthew G. Knepley if (ornt) { 38489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3849476787b7SMatthew 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; 3850b5a892a1SMatthew G. Knepley } 3851b5a892a1SMatthew G. Knepley if (*points) { 3852b5a892a1SMatthew G. Knepley closure = *points; 3853b5a892a1SMatthew G. Knepley } else { 3854b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38559566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3857b5a892a1SMatthew G. Knepley } 385809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3859b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3860b5a892a1SMatthew G. Knepley closure[off++] = p; 3861b5a892a1SMatthew G. Knepley closure[off++] = 0; 3862b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3863b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3864b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3865b5a892a1SMatthew G. Knepley } 3866b5a892a1SMatthew G. Knepley } else { 386785036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3868b5a892a1SMatthew G. Knepley 3869b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3870b5a892a1SMatthew G. Knepley closure[off++] = p; 3871b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3872b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3873b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3874b5a892a1SMatthew G. Knepley 38759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3876b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3877b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3878b5a892a1SMatthew G. Knepley } 3879b5a892a1SMatthew G. Knepley } 388009015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3881b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3882b5a892a1SMatthew G. Knepley if (points) *points = closure; 38833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3884b5a892a1SMatthew G. Knepley } 3885b5a892a1SMatthew G. Knepley 3886d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3887d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3888d71ae5a4SJacob Faibussowitsch { 388985036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3890b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3891b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3892b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3893b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3894b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3895b5a892a1SMatthew G. Knepley 3896b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 38979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 389809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 38999566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3900b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3901b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3902b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39039371c9d4SSatish Balay if (*points) { 39049371c9d4SSatish Balay pts = *points; 39059371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3906b5a892a1SMatthew G. Knepley c = 0; 3907b5a892a1SMatthew G. Knepley pts[c++] = point; 3908b5a892a1SMatthew G. Knepley pts[c++] = o; 39099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 39109566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 39119371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39129371c9d4SSatish Balay pts[c++] = closure[cl]; 39139371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39149371c9d4SSatish Balay } 39159566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 39169371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39179371c9d4SSatish Balay pts[c++] = closure[cl]; 39189371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39199371c9d4SSatish Balay } 39209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3921b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 39229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3923b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3924b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3925b5a892a1SMatthew G. Knepley } 392609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3927b5a892a1SMatthew G. Knepley if (dim >= 3) { 3928b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3929b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3930b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3931b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3932b5a892a1SMatthew G. Knepley 39339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 393485036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 393509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3936b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3937b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3938b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3939b5a892a1SMatthew G. Knepley 39409371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39419371c9d4SSatish Balay if (pts[i] == cp) break; 3942b5a892a1SMatthew G. Knepley if (i == c) { 39439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3944b5a892a1SMatthew G. Knepley pts[c++] = cp; 3945b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3946b5a892a1SMatthew G. Knepley } 3947b5a892a1SMatthew G. Knepley } 394809015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3949b5a892a1SMatthew G. Knepley } 3950b5a892a1SMatthew G. Knepley } 3951b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3952b5a892a1SMatthew G. Knepley *points = pts; 39533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3954b5a892a1SMatthew G. Knepley } 3955b5a892a1SMatthew G. Knepley 3956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3957d71ae5a4SJacob Faibussowitsch { 3958b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3959b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3960b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3961b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3962b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3963b5a892a1SMatthew G. Knepley 3964b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39659566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3966b5a892a1SMatthew G. Knepley if (depth == 1) { 39679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3969b5a892a1SMatthew G. Knepley } 39709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3971476787b7SMatthew 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; 3972c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39739566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3975b5a892a1SMatthew G. Knepley } 39769566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3977b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3978b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3979b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39809566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39819371c9d4SSatish Balay if (*points) { 39829371c9d4SSatish Balay closure = *points; 39839371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3984b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3985b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3986b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3987b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3988b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3989b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3990b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3991b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3992b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3993b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 399485036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 399509015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 3996b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3997b5a892a1SMatthew G. Knepley 3998b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 399985036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 400063a3b9bcSJacob 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); 4001b5a892a1SMatthew G. Knepley } 400209015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4003b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4004b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4005b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4006b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 40079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4008b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4009b5a892a1SMatthew G. Knepley PetscInt c; 4010b5a892a1SMatthew G. Knepley 4011b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4012b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4013b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4014b5a892a1SMatthew G. Knepley } 4015b5a892a1SMatthew G. Knepley if (c == closureSize) { 4016b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4017b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4018b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4019b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4020b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4021b5a892a1SMatthew G. Knepley } 4022b5a892a1SMatthew G. Knepley } 402309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4024b5a892a1SMatthew G. Knepley } 40259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4026b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4027b5a892a1SMatthew G. Knepley if (points) *points = closure; 40283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4029b5a892a1SMatthew G. Knepley } 4030b5a892a1SMatthew G. Knepley 4031552f7358SJed Brown /*@C 4032eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4033552f7358SJed Brown 4034a1cb98faSBarry Smith Not Collective 4035552f7358SJed Brown 4036552f7358SJed Brown Input Parameters: 4037a1cb98faSBarry Smith + dm - The `DMPLEX` 4038b5a892a1SMatthew G. Knepley . p - The mesh point 4039a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4040552f7358SJed Brown 40416b867d5aSJose E. Roman Input/Output Parameter: 40426b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 404320f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40446b867d5aSJose E. Roman 40456b867d5aSJose E. Roman Output Parameter: 404620f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4047552f7358SJed Brown 4048a1cb98faSBarry Smith Level: beginner 4049a1cb98faSBarry Smith 4050552f7358SJed Brown Note: 405120f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4052552f7358SJed Brown 405360225df5SJacob Faibussowitsch Fortran Notes: 405420f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40553813dfbdSMatthew G Knepley 40561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4057552f7358SJed Brown @*/ 4058d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4059d71ae5a4SJacob Faibussowitsch { 4060b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4061552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40624f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40634f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40669bf0dad6SMatthew G. Knepley } 40679bf0dad6SMatthew G. Knepley 4068552f7358SJed Brown /*@C 4069eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4070552f7358SJed Brown 4071a1cb98faSBarry Smith Not Collective 4072552f7358SJed Brown 4073552f7358SJed Brown Input Parameters: 4074a1cb98faSBarry Smith + dm - The `DMPLEX` 4075b5a892a1SMatthew G. Knepley . p - The mesh point 4076a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 407720f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4078b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4079552f7358SJed Brown 4080a1cb98faSBarry Smith Level: beginner 4081a1cb98faSBarry Smith 4082552f7358SJed Brown Note: 408320f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4084552f7358SJed Brown 40851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4086552f7358SJed Brown @*/ 4087d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4088d71ae5a4SJacob Faibussowitsch { 4089b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4090552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40914ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40929566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 40933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4094552f7358SJed Brown } 4095552f7358SJed Brown 4096552f7358SJed Brown /*@ 4097eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4098552f7358SJed Brown 4099a1cb98faSBarry Smith Not Collective 4100552f7358SJed Brown 4101552f7358SJed Brown Input Parameter: 410260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4103552f7358SJed Brown 4104552f7358SJed Brown Output Parameters: 4105552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4106552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4107552f7358SJed Brown 4108552f7358SJed Brown Level: beginner 4109552f7358SJed Brown 41101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4111552f7358SJed Brown @*/ 4112d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4113d71ae5a4SJacob Faibussowitsch { 4114552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4115552f7358SJed Brown 4116552f7358SJed Brown PetscFunctionBegin; 4117552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41181baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 41191baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 41203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4121552f7358SJed Brown } 4122552f7358SJed Brown 4123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4124d71ae5a4SJacob Faibussowitsch { 4125552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 41266302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4127552f7358SJed Brown 4128552f7358SJed Brown PetscFunctionBegin; 4129552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41339566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41346302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41356302a7fbSVaclav Hapla if (maxSupportSize) { 41369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4139552f7358SJed Brown } 41403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4141552f7358SJed Brown } 4142552f7358SJed Brown 4143d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4144d71ae5a4SJacob Faibussowitsch { 4145552f7358SJed Brown PetscFunctionBegin; 41469566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 41479566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 4148ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4149736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 415095602cf2SAlexis Marboeuf PetscSF sfNatural; 4151f94b4a02SBlaise Bourdin 41523dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 415495602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4155c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4156f94b4a02SBlaise Bourdin } 41573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4158552f7358SJed Brown } 4159552f7358SJed Brown 4160d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4161d71ae5a4SJacob Faibussowitsch { 41623dcd263cSBlaise Bourdin PetscInt i = 0; 41632adcc780SMatthew G. Knepley 41642adcc780SMatthew G. Knepley PetscFunctionBegin; 41659566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41669566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4167c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41683dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41693dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 417095602cf2SAlexis Marboeuf PetscSF sfNatural; 41713dcd263cSBlaise Bourdin 41723dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4174c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 417595602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4176c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41773dcd263cSBlaise Bourdin break; 41783dcd263cSBlaise Bourdin } 41793dcd263cSBlaise Bourdin } 41803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41812adcc780SMatthew G. Knepley } 41822adcc780SMatthew G. Knepley 4183552f7358SJed Brown /*@ 4184eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4185552f7358SJed Brown 4186a1cb98faSBarry Smith Not Collective 4187552f7358SJed Brown 4188552f7358SJed Brown Input Parameter: 418960225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4190552f7358SJed Brown 4191552f7358SJed Brown Level: beginner 4192552f7358SJed Brown 4193a1cb98faSBarry Smith Note: 4194a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4195a1cb98faSBarry Smith 41961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4197552f7358SJed Brown @*/ 4198d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4199d71ae5a4SJacob Faibussowitsch { 4200552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4201552f7358SJed Brown PetscInt *offsets; 4202552f7358SJed Brown PetscInt supportSize; 4203552f7358SJed Brown PetscInt pStart, pEnd, p; 4204552f7358SJed Brown 4205552f7358SJed Brown PetscFunctionBegin; 4206552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 420728b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 42089566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4209552f7358SJed Brown /* Calculate support sizes */ 42109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4211552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4212552f7358SJed Brown PetscInt dof, off, c; 4213552f7358SJed Brown 42149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 421648a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4217552f7358SJed Brown } 42189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4219552f7358SJed Brown /* Calculate supports */ 42209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 42219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 42229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4223552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4224552f7358SJed Brown PetscInt dof, off, c; 4225552f7358SJed Brown 42269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4228552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4229552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4230552f7358SJed Brown PetscInt offS; 4231552f7358SJed Brown 42329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42330d644c17SKarl Rupp 4234552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4235552f7358SJed Brown ++offsets[q]; 4236552f7358SJed Brown } 4237552f7358SJed Brown } 42389566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4241552f7358SJed Brown } 4242552f7358SJed Brown 4243d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4244d71ae5a4SJacob Faibussowitsch { 4245277ea44aSLisandro Dalcin IS stratumIS; 4246277ea44aSLisandro Dalcin 4247277ea44aSLisandro Dalcin PetscFunctionBegin; 42483ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 424976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4250277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4251277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42529566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4253277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42549566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42559371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42569371c9d4SSatish Balay overlap = PETSC_TRUE; 42579371c9d4SSatish Balay break; 42589371c9d4SSatish Balay } 4259277ea44aSLisandro Dalcin } 426063a3b9bcSJacob 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); 4261277ea44aSLisandro Dalcin } 42629566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42639566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4266277ea44aSLisandro Dalcin } 4267277ea44aSLisandro Dalcin 4268e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4269e91fa0a1SMatthew G. Knepley { 4270e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4271e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4272e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4273e91fa0a1SMatthew G. Knepley 4274e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4275e91fa0a1SMatthew G. Knepley { 4276e91fa0a1SMatthew G. Knepley DMLabel label2; 4277e91fa0a1SMatthew G. Knepley 4278e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4279e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4280e91fa0a1SMatthew G. Knepley } 4281e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4282e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4283e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4284e91fa0a1SMatthew G. Knepley 4285e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4286e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4287e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4288e91fa0a1SMatthew G. Knepley } 4289e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4290e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4291e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4292e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4293e91fa0a1SMatthew G. Knepley } 4294e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4295e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4296e91fa0a1SMatthew G. Knepley PetscInt d; 4297e91fa0a1SMatthew G. Knepley 4298e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4299e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4300e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4301e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4302e91fa0a1SMatthew G. Knepley } 4303e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4304e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4305e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4306e91fa0a1SMatthew G. Knepley } 4307e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4308e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4309e91fa0a1SMatthew G. Knepley } 4310e91fa0a1SMatthew G. Knepley 4311e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4312e91fa0a1SMatthew G. Knepley { 4313e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4314e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4315e91fa0a1SMatthew G. Knepley 4316e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4317e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4318e91fa0a1SMatthew G. Knepley { 4319e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4320e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4321e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4322e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4323e91fa0a1SMatthew G. Knepley 4324e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4325e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4326e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4327e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4328e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4329e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4330e91fa0a1SMatthew G. Knepley ++numRoots; 4331e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4332e91fa0a1SMatthew G. Knepley ++numLeaves; 4333e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4334e91fa0a1SMatthew G. Knepley /* Isolated points */ 4335e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4336e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4337e91fa0a1SMatthew G. Knepley } 4338e91fa0a1SMatthew G. Knepley } 4339e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4340e91fa0a1SMatthew G. Knepley } 4341e91fa0a1SMatthew G. Knepley 4342e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4343e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4344e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4345e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4346e91fa0a1SMatthew G. Knepley 4347e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4348e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4349e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4350e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4351e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4352e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4353e91fa0a1SMatthew G. Knepley } 4354e91fa0a1SMatthew G. Knepley } 4355e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4356e91fa0a1SMatthew G. Knepley } else { 4357e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4358e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4359e91fa0a1SMatthew G. Knepley 4360e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4361e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4362e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4363e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4364e91fa0a1SMatthew G. Knepley 4365e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4366e91fa0a1SMatthew G. Knepley const PetscInt *support; 4367e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4368e91fa0a1SMatthew G. Knepley 4369e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4370e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4371e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4372e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4373e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4374e91fa0a1SMatthew G. Knepley } 4375e91fa0a1SMatthew G. Knepley } 4376e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4377e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4378e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4379e91fa0a1SMatthew G. Knepley } 4380e91fa0a1SMatthew G. Knepley } 4381e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4382e91fa0a1SMatthew G. Knepley } 4383e91fa0a1SMatthew G. Knepley 4384552f7358SJed Brown /*@ 4385a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4386552f7358SJed Brown 438720f4b53cSBarry Smith Collective 4388552f7358SJed Brown 4389552f7358SJed Brown Input Parameter: 439060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4391552f7358SJed Brown 4392a1cb98faSBarry Smith Level: beginner 4393552f7358SJed Brown 4394552f7358SJed Brown Notes: 4395a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4396a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4397a4e35b19SJacob Faibussowitsch 4398a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4399a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4400a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4401b1bb481bSMatthew 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 4402a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4403a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4404a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4405552f7358SJed Brown 4406b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4407b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4408b1bb481bSMatthew 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 4409b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4410a1cb98faSBarry Smith .vb 4411a1cb98faSBarry Smith cone(c0) = {e0, v2} 4412a1cb98faSBarry Smith cone(e0) = {v0, v1} 4413a1cb98faSBarry Smith .ve 4414a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4415a1cb98faSBarry Smith .vb 4416a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4417a1cb98faSBarry Smith depth 1 = {e0, c0} 4418a1cb98faSBarry Smith .ve 4419b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4420b1bb481bSMatthew Knepley 4421a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4422552f7358SJed Brown 44231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4424552f7358SJed Brown @*/ 4425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4426d71ae5a4SJacob Faibussowitsch { 4427df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4428aa50250dSMatthew G. Knepley DMLabel label; 4429e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4430552f7358SJed Brown 4431552f7358SJed Brown PetscFunctionBegin; 4432552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4434277ea44aSLisandro Dalcin 4435e91fa0a1SMatthew G. Knepley // Create depth label 44369566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4438277ea44aSLisandro Dalcin 4439e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4440e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4441e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4442552f7358SJed Brown 4443bf4602e4SToby Isaac { /* just in case there is an empty process */ 4444bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4445bf4602e4SToby Isaac 44469566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4447712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 444848a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4449bf4602e4SToby Isaac } 44509566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44519566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4453552f7358SJed Brown } 4454552f7358SJed Brown 4455d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4456d71ae5a4SJacob Faibussowitsch { 4457412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4458412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4459ba2698f1SMatthew G. Knepley 4460412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4464ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4465ba2698f1SMatthew G. Knepley if (depth <= 1) { 4466ba2698f1SMatthew G. Knepley switch (pdepth) { 4467d71ae5a4SJacob Faibussowitsch case 0: 4468d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4469d71ae5a4SJacob Faibussowitsch break; 4470ba2698f1SMatthew G. Knepley case 1: 4471ba2698f1SMatthew G. Knepley switch (coneSize) { 4472d71ae5a4SJacob Faibussowitsch case 2: 4473d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4474d71ae5a4SJacob Faibussowitsch break; 4475d71ae5a4SJacob Faibussowitsch case 3: 4476d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4477d71ae5a4SJacob Faibussowitsch break; 4478ba2698f1SMatthew G. Knepley case 4: 4479ba2698f1SMatthew G. Knepley switch (dim) { 4480d71ae5a4SJacob Faibussowitsch case 2: 4481d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4482d71ae5a4SJacob Faibussowitsch break; 4483d71ae5a4SJacob Faibussowitsch case 3: 4484d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4485d71ae5a4SJacob Faibussowitsch break; 4486d71ae5a4SJacob Faibussowitsch default: 4487d71ae5a4SJacob Faibussowitsch break; 4488ba2698f1SMatthew G. Knepley } 4489ba2698f1SMatthew G. Knepley break; 4490d71ae5a4SJacob Faibussowitsch case 5: 4491d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4492d71ae5a4SJacob Faibussowitsch break; 4493d71ae5a4SJacob Faibussowitsch case 6: 4494d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4495d71ae5a4SJacob Faibussowitsch break; 4496d71ae5a4SJacob Faibussowitsch case 8: 4497d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4498d71ae5a4SJacob Faibussowitsch break; 4499d71ae5a4SJacob Faibussowitsch default: 4500d71ae5a4SJacob Faibussowitsch break; 4501ba2698f1SMatthew G. Knepley } 4502ba2698f1SMatthew G. Knepley } 4503ba2698f1SMatthew G. Knepley } else { 4504ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4505ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4506ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4507ba2698f1SMatthew G. Knepley switch (dim) { 4508ba2698f1SMatthew G. Knepley case 1: 4509ba2698f1SMatthew G. Knepley switch (coneSize) { 4510d71ae5a4SJacob Faibussowitsch case 2: 4511d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4512d71ae5a4SJacob Faibussowitsch break; 4513d71ae5a4SJacob Faibussowitsch default: 4514d71ae5a4SJacob Faibussowitsch break; 4515ba2698f1SMatthew G. Knepley } 4516ba2698f1SMatthew G. Knepley break; 4517ba2698f1SMatthew G. Knepley case 2: 4518ba2698f1SMatthew G. Knepley switch (coneSize) { 4519d71ae5a4SJacob Faibussowitsch case 3: 4520d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4521d71ae5a4SJacob Faibussowitsch break; 4522d71ae5a4SJacob Faibussowitsch case 4: 4523d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4524d71ae5a4SJacob Faibussowitsch break; 4525d71ae5a4SJacob Faibussowitsch default: 4526d71ae5a4SJacob Faibussowitsch break; 4527ba2698f1SMatthew G. Knepley } 4528ba2698f1SMatthew G. Knepley break; 4529ba2698f1SMatthew G. Knepley case 3: 4530ba2698f1SMatthew G. Knepley switch (coneSize) { 4531d71ae5a4SJacob Faibussowitsch case 4: 4532d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4533d71ae5a4SJacob Faibussowitsch break; 45349371c9d4SSatish Balay case 5: { 4535da9060c4SMatthew G. Knepley const PetscInt *cone; 4536da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4537da9060c4SMatthew G. Knepley 45389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4540da9060c4SMatthew G. Knepley switch (faceConeSize) { 4541d71ae5a4SJacob Faibussowitsch case 3: 4542d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4543d71ae5a4SJacob Faibussowitsch break; 4544d71ae5a4SJacob Faibussowitsch case 4: 4545d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4546d71ae5a4SJacob Faibussowitsch break; 4547da9060c4SMatthew G. Knepley } 45489371c9d4SSatish Balay } break; 4549d71ae5a4SJacob Faibussowitsch case 6: 4550d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4551d71ae5a4SJacob Faibussowitsch break; 4552d71ae5a4SJacob Faibussowitsch default: 4553d71ae5a4SJacob Faibussowitsch break; 4554ba2698f1SMatthew G. Knepley } 4555ba2698f1SMatthew G. Knepley break; 4556d71ae5a4SJacob Faibussowitsch default: 4557d71ae5a4SJacob Faibussowitsch break; 4558ba2698f1SMatthew G. Knepley } 4559ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4560ba2698f1SMatthew G. Knepley switch (coneSize) { 4561d71ae5a4SJacob Faibussowitsch case 2: 4562d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4563d71ae5a4SJacob Faibussowitsch break; 4564d71ae5a4SJacob Faibussowitsch case 3: 4565d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4566d71ae5a4SJacob Faibussowitsch break; 4567d71ae5a4SJacob Faibussowitsch case 4: 4568d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4569d71ae5a4SJacob Faibussowitsch break; 4570d71ae5a4SJacob Faibussowitsch default: 4571d71ae5a4SJacob Faibussowitsch break; 4572ba2698f1SMatthew G. Knepley } 4573ba2698f1SMatthew G. Knepley } 4574ba2698f1SMatthew G. Knepley } 4575412e9a14SMatthew G. Knepley *pt = ct; 45763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4577ba2698f1SMatthew G. Knepley } 4578412e9a14SMatthew G. Knepley 4579412e9a14SMatthew G. Knepley /*@ 4580412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4581412e9a14SMatthew G. Knepley 458220f4b53cSBarry Smith Collective 4583412e9a14SMatthew G. Knepley 4584412e9a14SMatthew G. Knepley Input Parameter: 458560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4586412e9a14SMatthew G. Knepley 4587412e9a14SMatthew G. Knepley Level: developer 4588412e9a14SMatthew G. Knepley 4589a1cb98faSBarry Smith Note: 4590a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4591a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4592a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4593412e9a14SMatthew G. Knepley 4594a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4595a1cb98faSBarry Smith 45961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4597412e9a14SMatthew G. Knepley @*/ 4598d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4599d71ae5a4SJacob Faibussowitsch { 4600412e9a14SMatthew G. Knepley DM_Plex *mesh; 4601412e9a14SMatthew G. Knepley DMLabel ctLabel; 4602412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4603412e9a14SMatthew G. Knepley 4604412e9a14SMatthew G. Knepley PetscFunctionBegin; 4605412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4606412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 46079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 46089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 46099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 461021027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 461121027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4612412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4613327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4614412e9a14SMatthew G. Knepley PetscInt pdepth; 4615412e9a14SMatthew G. Knepley 46169566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 46179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4618476787b7SMatthew 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); 46199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 462021027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4621412e9a14SMatthew G. Knepley } 46229566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 46239566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 46243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4625ba2698f1SMatthew G. Knepley } 4626ba2698f1SMatthew G. Knepley 4627552f7358SJed Brown /*@C 4628552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4629552f7358SJed Brown 4630552f7358SJed Brown Not Collective 4631552f7358SJed Brown 4632552f7358SJed Brown Input Parameters: 4633a1cb98faSBarry Smith + dm - The `DMPLEX` object 4634552f7358SJed Brown . numPoints - The number of input points for the join 4635552f7358SJed Brown - points - The input points 4636552f7358SJed Brown 4637552f7358SJed Brown Output Parameters: 4638552f7358SJed Brown + numCoveredPoints - The number of points in the join 4639552f7358SJed Brown - coveredPoints - The points in the join 4640552f7358SJed Brown 4641552f7358SJed Brown Level: intermediate 4642552f7358SJed Brown 4643a1cb98faSBarry Smith Note: 4644a1cb98faSBarry Smith Currently, this is restricted to a single level join 4645552f7358SJed Brown 464660225df5SJacob Faibussowitsch Fortran Notes: 464720f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46483813dfbdSMatthew G Knepley 46491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4650552f7358SJed Brown @*/ 4651d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4652d71ae5a4SJacob Faibussowitsch { 4653552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4654552f7358SJed Brown PetscInt *join[2]; 4655552f7358SJed Brown PetscInt joinSize, i = 0; 4656552f7358SJed Brown PetscInt dof, off, p, c, m; 46576302a7fbSVaclav Hapla PetscInt maxSupportSize; 4658552f7358SJed Brown 4659552f7358SJed Brown PetscFunctionBegin; 4660552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46614f572ea9SToby Isaac PetscAssertPointer(points, 3); 46624f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46634f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46646302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46656302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46666302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4667552f7358SJed Brown /* Copy in support of first point */ 46689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4670ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4671552f7358SJed Brown /* Check each successive support */ 4672552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4673552f7358SJed Brown PetscInt newJoinSize = 0; 4674552f7358SJed Brown 46759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4677552f7358SJed Brown for (c = 0; c < dof; ++c) { 4678552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4679552f7358SJed Brown 4680552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4681552f7358SJed Brown if (point == join[i][m]) { 4682552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4683552f7358SJed Brown break; 4684552f7358SJed Brown } 4685552f7358SJed Brown } 4686552f7358SJed Brown } 4687552f7358SJed Brown joinSize = newJoinSize; 4688552f7358SJed Brown i = 1 - i; 4689552f7358SJed Brown } 4690552f7358SJed Brown *numCoveredPoints = joinSize; 4691552f7358SJed Brown *coveredPoints = join[i]; 46926302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 46933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4694552f7358SJed Brown } 4695552f7358SJed Brown 4696552f7358SJed Brown /*@C 4697552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4698552f7358SJed Brown 4699552f7358SJed Brown Not Collective 4700552f7358SJed Brown 4701552f7358SJed Brown Input Parameters: 4702a1cb98faSBarry Smith + dm - The `DMPLEX` object 4703552f7358SJed Brown . numPoints - The number of input points for the join 4704552f7358SJed Brown - points - The input points 4705552f7358SJed Brown 4706552f7358SJed Brown Output Parameters: 4707552f7358SJed Brown + numCoveredPoints - The number of points in the join 4708552f7358SJed Brown - coveredPoints - The points in the join 4709552f7358SJed Brown 4710552f7358SJed Brown Level: intermediate 4711552f7358SJed Brown 471260225df5SJacob Faibussowitsch Fortran Notes: 471320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4714a1cb98faSBarry Smith 47151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4716552f7358SJed Brown @*/ 4717d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4718d71ae5a4SJacob Faibussowitsch { 4719552f7358SJed Brown PetscFunctionBegin; 4720552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47214f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 47224f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 47234f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47249566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4725d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 47263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4727552f7358SJed Brown } 4728552f7358SJed Brown 4729552f7358SJed Brown /*@C 4730552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4731552f7358SJed Brown 4732552f7358SJed Brown Not Collective 4733552f7358SJed Brown 4734552f7358SJed Brown Input Parameters: 4735a1cb98faSBarry Smith + dm - The `DMPLEX` object 4736552f7358SJed Brown . numPoints - The number of input points for the join 4737552f7358SJed Brown - points - The input points 4738552f7358SJed Brown 4739552f7358SJed Brown Output Parameters: 4740552f7358SJed Brown + numCoveredPoints - The number of points in the join 4741552f7358SJed Brown - coveredPoints - The points in the join 4742552f7358SJed Brown 4743552f7358SJed Brown Level: intermediate 4744552f7358SJed Brown 474560225df5SJacob Faibussowitsch Fortran Notes: 474620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4747a1cb98faSBarry Smith 47481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4749552f7358SJed Brown @*/ 4750d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4751d71ae5a4SJacob Faibussowitsch { 4752552f7358SJed Brown PetscInt *offsets, **closures; 4753552f7358SJed Brown PetscInt *join[2]; 4754552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 475524c766afSToby Isaac PetscInt p, d, c, m, ms; 4756552f7358SJed Brown 4757552f7358SJed Brown PetscFunctionBegin; 4758552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47594f572ea9SToby Isaac PetscAssertPointer(points, 3); 47604f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47614f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4762552f7358SJed Brown 47639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47666302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 476724c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4770552f7358SJed Brown 4771552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4772552f7358SJed Brown PetscInt closureSize; 4773552f7358SJed Brown 47749566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47750d644c17SKarl Rupp 4776552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4777552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4778552f7358SJed Brown PetscInt pStart, pEnd, i; 4779552f7358SJed Brown 47809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4781552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4782552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4783552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4784552f7358SJed Brown break; 4785552f7358SJed Brown } 4786552f7358SJed Brown } 4787552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4788552f7358SJed Brown } 478963a3b9bcSJacob 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); 4790552f7358SJed Brown } 4791552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4792552f7358SJed Brown PetscInt dof; 4793552f7358SJed Brown 4794552f7358SJed Brown /* Copy in support of first point */ 4795552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4796ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4797552f7358SJed Brown /* Check each successive cone */ 4798552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4799552f7358SJed Brown PetscInt newJoinSize = 0; 4800552f7358SJed Brown 4801552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4802552f7358SJed Brown for (c = 0; c < dof; ++c) { 4803552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4804552f7358SJed Brown 4805552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4806552f7358SJed Brown if (point == join[i][m]) { 4807552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4808552f7358SJed Brown break; 4809552f7358SJed Brown } 4810552f7358SJed Brown } 4811552f7358SJed Brown } 4812552f7358SJed Brown joinSize = newJoinSize; 4813552f7358SJed Brown i = 1 - i; 4814552f7358SJed Brown } 4815552f7358SJed Brown if (joinSize) break; 4816552f7358SJed Brown } 4817552f7358SJed Brown *numCoveredPoints = joinSize; 4818552f7358SJed Brown *coveredPoints = join[i]; 481948a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 48209566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 48219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48226302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 48233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4824552f7358SJed Brown } 4825552f7358SJed Brown 4826552f7358SJed Brown /*@C 4827552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4828552f7358SJed Brown 4829552f7358SJed Brown Not Collective 4830552f7358SJed Brown 4831552f7358SJed Brown Input Parameters: 4832a1cb98faSBarry Smith + dm - The `DMPLEX` object 4833552f7358SJed Brown . numPoints - The number of input points for the meet 4834552f7358SJed Brown - points - The input points 4835552f7358SJed Brown 4836552f7358SJed Brown Output Parameters: 483760225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 483860225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4839552f7358SJed Brown 4840552f7358SJed Brown Level: intermediate 4841552f7358SJed Brown 4842a1cb98faSBarry Smith Note: 4843a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4844552f7358SJed Brown 48453813dfbdSMatthew G Knepley Fortran Notes: 484620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48473813dfbdSMatthew G Knepley 48481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4849552f7358SJed Brown @*/ 4850d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4851d71ae5a4SJacob Faibussowitsch { 4852552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4853552f7358SJed Brown PetscInt *meet[2]; 4854552f7358SJed Brown PetscInt meetSize, i = 0; 4855552f7358SJed Brown PetscInt dof, off, p, c, m; 48566302a7fbSVaclav Hapla PetscInt maxConeSize; 4857552f7358SJed Brown 4858552f7358SJed Brown PetscFunctionBegin; 4859552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48604f572ea9SToby Isaac PetscAssertPointer(points, 3); 48614f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48624f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48636302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48646302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48656302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4866552f7358SJed Brown /* Copy in cone of first point */ 48679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4869ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4870552f7358SJed Brown /* Check each successive cone */ 4871552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4872552f7358SJed Brown PetscInt newMeetSize = 0; 4873552f7358SJed Brown 48749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4876552f7358SJed Brown for (c = 0; c < dof; ++c) { 4877552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4878552f7358SJed Brown 4879552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4880552f7358SJed Brown if (point == meet[i][m]) { 4881552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4882552f7358SJed Brown break; 4883552f7358SJed Brown } 4884552f7358SJed Brown } 4885552f7358SJed Brown } 4886552f7358SJed Brown meetSize = newMeetSize; 4887552f7358SJed Brown i = 1 - i; 4888552f7358SJed Brown } 4889552f7358SJed Brown *numCoveringPoints = meetSize; 4890552f7358SJed Brown *coveringPoints = meet[i]; 48916302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4893552f7358SJed Brown } 4894552f7358SJed Brown 4895552f7358SJed Brown /*@C 4896552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4897552f7358SJed Brown 4898552f7358SJed Brown Not Collective 4899552f7358SJed Brown 4900552f7358SJed Brown Input Parameters: 4901a1cb98faSBarry Smith + dm - The `DMPLEX` object 4902552f7358SJed Brown . numPoints - The number of input points for the meet 4903552f7358SJed Brown - points - The input points 4904552f7358SJed Brown 4905552f7358SJed Brown Output Parameters: 4906552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4907552f7358SJed Brown - coveredPoints - The points in the meet 4908552f7358SJed Brown 4909552f7358SJed Brown Level: intermediate 4910552f7358SJed Brown 491160225df5SJacob Faibussowitsch Fortran Notes: 491220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49133813dfbdSMatthew G Knepley 49141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4915552f7358SJed Brown @*/ 4916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4917d71ae5a4SJacob Faibussowitsch { 4918552f7358SJed Brown PetscFunctionBegin; 4919552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49204f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49214f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49224f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49239566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4924d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4926552f7358SJed Brown } 4927552f7358SJed Brown 4928552f7358SJed Brown /*@C 4929552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4930552f7358SJed Brown 4931552f7358SJed Brown Not Collective 4932552f7358SJed Brown 4933552f7358SJed Brown Input Parameters: 4934a1cb98faSBarry Smith + dm - The `DMPLEX` object 4935552f7358SJed Brown . numPoints - The number of input points for the meet 4936552f7358SJed Brown - points - The input points 4937552f7358SJed Brown 4938552f7358SJed Brown Output Parameters: 4939552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4940552f7358SJed Brown - coveredPoints - The points in the meet 4941552f7358SJed Brown 4942552f7358SJed Brown Level: intermediate 4943552f7358SJed Brown 494460225df5SJacob Faibussowitsch Fortran Notes: 494520f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49463813dfbdSMatthew G Knepley 49471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4948552f7358SJed Brown @*/ 4949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4950d71ae5a4SJacob Faibussowitsch { 4951552f7358SJed Brown PetscInt *offsets, **closures; 4952552f7358SJed Brown PetscInt *meet[2]; 4953552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 495424c766afSToby Isaac PetscInt p, h, c, m, mc; 4955552f7358SJed Brown 4956552f7358SJed Brown PetscFunctionBegin; 4957552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49584f572ea9SToby Isaac PetscAssertPointer(points, 3); 49594f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49604f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4961552f7358SJed Brown 49629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49656302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 496624c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4969552f7358SJed Brown 4970552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4971552f7358SJed Brown PetscInt closureSize; 4972552f7358SJed Brown 49739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49740d644c17SKarl Rupp 4975552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4976552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4977552f7358SJed Brown PetscInt pStart, pEnd, i; 4978552f7358SJed Brown 49799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4980552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4981552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4982552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4983552f7358SJed Brown break; 4984552f7358SJed Brown } 4985552f7358SJed Brown } 4986552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4987552f7358SJed Brown } 498863a3b9bcSJacob 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); 4989552f7358SJed Brown } 4990552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4991552f7358SJed Brown PetscInt dof; 4992552f7358SJed Brown 4993552f7358SJed Brown /* Copy in cone of first point */ 4994552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4995ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4996552f7358SJed Brown /* Check each successive cone */ 4997552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4998552f7358SJed Brown PetscInt newMeetSize = 0; 4999552f7358SJed Brown 5000552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5001552f7358SJed Brown for (c = 0; c < dof; ++c) { 5002552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5003552f7358SJed Brown 5004552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5005552f7358SJed Brown if (point == meet[i][m]) { 5006552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5007552f7358SJed Brown break; 5008552f7358SJed Brown } 5009552f7358SJed Brown } 5010552f7358SJed Brown } 5011552f7358SJed Brown meetSize = newMeetSize; 5012552f7358SJed Brown i = 1 - i; 5013552f7358SJed Brown } 5014552f7358SJed Brown if (meetSize) break; 5015552f7358SJed Brown } 5016552f7358SJed Brown *numCoveredPoints = meetSize; 5017552f7358SJed Brown *coveredPoints = meet[i]; 501848a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 50199566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50216302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 50223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5023552f7358SJed Brown } 5024552f7358SJed Brown 50254e3744c5SMatthew G. Knepley /*@C 5026a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50274e3744c5SMatthew G. Knepley 50284e3744c5SMatthew G. Knepley Not Collective 50294e3744c5SMatthew G. Knepley 50304e3744c5SMatthew G. Knepley Input Parameters: 5031a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5032a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50334e3744c5SMatthew G. Knepley 50342fe279fdSBarry Smith Output Parameter: 5035a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50364e3744c5SMatthew G. Knepley 50374e3744c5SMatthew G. Knepley Level: intermediate 50384e3744c5SMatthew G. Knepley 5039a1cb98faSBarry Smith Note: 50403c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50414e3744c5SMatthew G. Knepley 50421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50434e3744c5SMatthew G. Knepley @*/ 5044d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5045d71ae5a4SJacob Faibussowitsch { 50464e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50474e3744c5SMatthew G. Knepley 50484e3744c5SMatthew G. Knepley PetscFunctionBegin; 50494e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50504e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50514f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50524e3744c5SMatthew G. Knepley 50534e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50563ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50589566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50593ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50604e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50614e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50624e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50634e3744c5SMatthew G. Knepley 50649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50703ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50714e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50723ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50733ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50744e3744c5SMatthew G. Knepley } 50759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50789566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50793ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50804e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50813ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50824e3744c5SMatthew G. Knepley } 50834e3744c5SMatthew G. Knepley } 50844e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50864e3744c5SMatthew G. Knepley } 50874e3744c5SMatthew G. Knepley 50887cd05799SMatthew G. Knepley /*@C 50897cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50907cd05799SMatthew G. Knepley 50917cd05799SMatthew G. Knepley Not Collective 50927cd05799SMatthew G. Knepley 50937cd05799SMatthew G. Knepley Input Parameters: 5094a1cb98faSBarry Smith + dm - The `DMPLEX` 50957cd05799SMatthew G. Knepley . cellDim - The cell dimension 50967cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 50977cd05799SMatthew G. Knepley 50982fe279fdSBarry Smith Output Parameter: 50997cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 51007cd05799SMatthew G. Knepley 51017cd05799SMatthew G. Knepley Level: developer 51027cd05799SMatthew G. Knepley 5103a1cb98faSBarry Smith Note: 51047cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 51057cd05799SMatthew G. Knepley 51061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51077cd05799SMatthew G. Knepley @*/ 5108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5109d71ae5a4SJacob Faibussowitsch { 511082f516ccSBarry Smith MPI_Comm comm; 5111552f7358SJed Brown 5112552f7358SJed Brown PetscFunctionBegin; 51139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 51144f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5115552f7358SJed Brown switch (cellDim) { 5116d71ae5a4SJacob Faibussowitsch case 0: 5117d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5118d71ae5a4SJacob Faibussowitsch break; 5119d71ae5a4SJacob Faibussowitsch case 1: 5120d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5121d71ae5a4SJacob Faibussowitsch break; 5122552f7358SJed Brown case 2: 5123552f7358SJed Brown switch (numCorners) { 512419436ca2SJed Brown case 3: /* triangle */ 512519436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5126552f7358SJed Brown break; 512719436ca2SJed Brown case 4: /* quadrilateral */ 512819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5129552f7358SJed Brown break; 513019436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 513119436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5132552f7358SJed Brown break; 513319436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 513419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5135552f7358SJed Brown break; 5136d71ae5a4SJacob Faibussowitsch default: 5137d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5138552f7358SJed Brown } 5139552f7358SJed Brown break; 5140552f7358SJed Brown case 3: 5141552f7358SJed Brown switch (numCorners) { 514219436ca2SJed Brown case 4: /* tetradehdron */ 514319436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5144552f7358SJed Brown break; 514519436ca2SJed Brown case 6: /* tet cohesive cells */ 514619436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5147552f7358SJed Brown break; 514819436ca2SJed Brown case 8: /* hexahedron */ 514919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5150552f7358SJed Brown break; 515119436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 515219436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5153552f7358SJed Brown break; 515419436ca2SJed Brown case 10: /* quadratic tetrahedron */ 515519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5156552f7358SJed Brown break; 515719436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 515819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5159552f7358SJed Brown break; 516019436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 516119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5162552f7358SJed Brown break; 516319436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 516419436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5165552f7358SJed Brown break; 5166d71ae5a4SJacob Faibussowitsch default: 5167d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5168552f7358SJed Brown } 5169552f7358SJed Brown break; 5170d71ae5a4SJacob Faibussowitsch default: 5171d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5172552f7358SJed Brown } 51733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5174552f7358SJed Brown } 5175552f7358SJed Brown 5176552f7358SJed Brown /*@ 5177a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5178552f7358SJed Brown 5179552f7358SJed Brown Not Collective 5180552f7358SJed Brown 5181aa50250dSMatthew G. Knepley Input Parameter: 5182a1cb98faSBarry Smith . dm - The `DMPLEX` object 5183552f7358SJed Brown 5184aa50250dSMatthew G. Knepley Output Parameter: 5185a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5186552f7358SJed Brown 5187552f7358SJed Brown Level: developer 5188552f7358SJed Brown 51891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5190aa50250dSMatthew G. Knepley @*/ 5191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5192d71ae5a4SJacob Faibussowitsch { 5193aa50250dSMatthew G. Knepley PetscFunctionBegin; 5194aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51954f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5196c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 51973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5198aa50250dSMatthew G. Knepley } 5199aa50250dSMatthew G. Knepley 5200aa50250dSMatthew G. Knepley /*@ 5201aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5202aa50250dSMatthew G. Knepley 5203aa50250dSMatthew G. Knepley Not Collective 5204aa50250dSMatthew G. Knepley 5205aa50250dSMatthew G. Knepley Input Parameter: 5206a1cb98faSBarry Smith . dm - The `DMPLEX` object 5207aa50250dSMatthew G. Knepley 5208aa50250dSMatthew G. Knepley Output Parameter: 5209aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5210aa50250dSMatthew G. Knepley 5211aa50250dSMatthew G. Knepley Level: developer 5212552f7358SJed Brown 5213b1bb481bSMatthew Knepley Notes: 5214a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5215a1cb98faSBarry Smith 5216a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5217a1cb98faSBarry Smith 5218dc287ab2SVaclav Hapla An empty mesh gives -1. 5219b1bb481bSMatthew Knepley 52201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5221552f7358SJed Brown @*/ 5222d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5223d71ae5a4SJacob Faibussowitsch { 52249f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5225aa50250dSMatthew G. Knepley DMLabel label; 5226aa50250dSMatthew G. Knepley PetscInt d = 0; 5227552f7358SJed Brown 5228552f7358SJed Brown PetscFunctionBegin; 5229552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52304f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52319f4ada15SMatthew G. Knepley if (mesh->tr) { 52329f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52339f4ada15SMatthew G. Knepley } else { 52349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52359566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5236552f7358SJed Brown *depth = d - 1; 52379f4ada15SMatthew G. Knepley } 52383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5239552f7358SJed Brown } 5240552f7358SJed Brown 5241552f7358SJed Brown /*@ 524220f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5243552f7358SJed Brown 5244552f7358SJed Brown Not Collective 5245552f7358SJed Brown 5246552f7358SJed Brown Input Parameters: 5247a1cb98faSBarry Smith + dm - The `DMPLEX` object 5248570fa34dSVaclav Hapla - depth - The requested depth 5249552f7358SJed Brown 5250552f7358SJed Brown Output Parameters: 525120f4b53cSBarry Smith + start - The first point at this `depth` 525220f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5253552f7358SJed Brown 5254552f7358SJed Brown Level: developer 5255552f7358SJed Brown 5256a1cb98faSBarry Smith Notes: 5257a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5258a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5259a1cb98faSBarry Smith higher dimension, e.g., "edges". 5260a1cb98faSBarry Smith 52612827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5262552f7358SJed Brown @*/ 5263d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5264d71ae5a4SJacob Faibussowitsch { 52659f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5266aa50250dSMatthew G. Knepley DMLabel label; 526763d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5268552f7358SJed Brown 5269552f7358SJed Brown PetscFunctionBegin; 5270552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52719371c9d4SSatish Balay if (start) { 52724f572ea9SToby Isaac PetscAssertPointer(start, 3); 52739371c9d4SSatish Balay *start = 0; 52749371c9d4SSatish Balay } 52759371c9d4SSatish Balay if (end) { 52764f572ea9SToby Isaac PetscAssertPointer(end, 4); 52779371c9d4SSatish Balay *end = 0; 52789371c9d4SSatish Balay } 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52803ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5281570fa34dSVaclav Hapla if (depth < 0) { 528263d1a920SMatthew G. Knepley if (start) *start = pStart; 528363d1a920SMatthew G. Knepley if (end) *end = pEnd; 52843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5285552f7358SJed Brown } 52869f4ada15SMatthew G. Knepley if (mesh->tr) { 52879f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52889f4ada15SMatthew G. Knepley } else { 52899566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 529028b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5291570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52929f4ada15SMatthew G. Knepley } 52933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5294552f7358SJed Brown } 5295552f7358SJed Brown 5296552f7358SJed Brown /*@ 529720f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5298552f7358SJed Brown 5299552f7358SJed Brown Not Collective 5300552f7358SJed Brown 5301552f7358SJed Brown Input Parameters: 5302a1cb98faSBarry Smith + dm - The `DMPLEX` object 5303570fa34dSVaclav Hapla - height - The requested height 5304552f7358SJed Brown 5305552f7358SJed Brown Output Parameters: 530620f4b53cSBarry Smith + start - The first point at this `height` 530720f4b53cSBarry Smith - end - One beyond the last point at this `height` 5308552f7358SJed Brown 5309552f7358SJed Brown Level: developer 5310552f7358SJed Brown 5311a1cb98faSBarry Smith Notes: 5312a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5313a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5314a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5315a1cb98faSBarry Smith 53162827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5317552f7358SJed Brown @*/ 5318d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5319d71ae5a4SJacob Faibussowitsch { 5320aa50250dSMatthew G. Knepley DMLabel label; 532163d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5322552f7358SJed Brown 5323552f7358SJed Brown PetscFunctionBegin; 5324552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53259371c9d4SSatish Balay if (start) { 53264f572ea9SToby Isaac PetscAssertPointer(start, 3); 53279371c9d4SSatish Balay *start = 0; 53289371c9d4SSatish Balay } 53299371c9d4SSatish Balay if (end) { 53304f572ea9SToby Isaac PetscAssertPointer(end, 4); 53319371c9d4SSatish Balay *end = 0; 53329371c9d4SSatish Balay } 53339566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53343ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5335570fa34dSVaclav Hapla if (height < 0) { 533663d1a920SMatthew G. Knepley if (start) *start = pStart; 533763d1a920SMatthew G. Knepley if (end) *end = pEnd; 53383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5339552f7358SJed Brown } 53409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 534159e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 534259e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 534359e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 534459e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5346552f7358SJed Brown } 5347552f7358SJed Brown 5348ba2698f1SMatthew G. Knepley /*@ 534920f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 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 - point - The point 5356ba2698f1SMatthew G. Knepley 5357ba2698f1SMatthew G. Knepley Output Parameter: 535820f4b53cSBarry Smith . depth - The depth of the `point` 5359ba2698f1SMatthew G. Knepley 5360ba2698f1SMatthew G. Knepley Level: intermediate 5361ba2698f1SMatthew G. Knepley 53621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5363ba2698f1SMatthew G. Knepley @*/ 5364d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5365d71ae5a4SJacob Faibussowitsch { 5366ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5367ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53684f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53699566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5371ba2698f1SMatthew G. Knepley } 5372ba2698f1SMatthew G. Knepley 5373ba2698f1SMatthew G. Knepley /*@ 537420f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53750c0a32dcSVaclav Hapla 53760c0a32dcSVaclav Hapla Not Collective 53770c0a32dcSVaclav Hapla 5378d8d19677SJose E. Roman Input Parameters: 5379a1cb98faSBarry Smith + dm - The `DMPLEX` object 53800c0a32dcSVaclav Hapla - point - The point 53810c0a32dcSVaclav Hapla 53820c0a32dcSVaclav Hapla Output Parameter: 538320f4b53cSBarry Smith . height - The height of the `point` 53840c0a32dcSVaclav Hapla 53850c0a32dcSVaclav Hapla Level: intermediate 53860c0a32dcSVaclav Hapla 53871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53880c0a32dcSVaclav Hapla @*/ 5389d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5390d71ae5a4SJacob Faibussowitsch { 53910c0a32dcSVaclav Hapla PetscInt n, pDepth; 53920c0a32dcSVaclav Hapla 53930c0a32dcSVaclav Hapla PetscFunctionBegin; 53940c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53954f572ea9SToby Isaac PetscAssertPointer(height, 3); 53969566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 53979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 53980c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 53993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54000c0a32dcSVaclav Hapla } 54010c0a32dcSVaclav Hapla 54020c0a32dcSVaclav Hapla /*@ 5403a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5404ba2698f1SMatthew G. Knepley 5405ba2698f1SMatthew G. Knepley Not Collective 5406ba2698f1SMatthew G. Knepley 5407ba2698f1SMatthew G. Knepley Input Parameter: 5408a1cb98faSBarry Smith . dm - The `DMPLEX` object 5409ba2698f1SMatthew G. Knepley 5410ba2698f1SMatthew G. Knepley Output Parameter: 5411a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5412412e9a14SMatthew G. Knepley 5413ba2698f1SMatthew G. Knepley Level: developer 5414ba2698f1SMatthew G. Knepley 5415a1cb98faSBarry Smith Note: 5416a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5417a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5418a1cb98faSBarry Smith 54191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5420ba2698f1SMatthew G. Knepley @*/ 5421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5422d71ae5a4SJacob Faibussowitsch { 5423ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5424ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54254f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 54269566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5427ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5429ba2698f1SMatthew G. Knepley } 5430ba2698f1SMatthew G. Knepley 5431ba2698f1SMatthew G. Knepley /*@ 5432ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5433ba2698f1SMatthew G. Knepley 5434ba2698f1SMatthew G. Knepley Not Collective 5435ba2698f1SMatthew G. Knepley 5436d8d19677SJose E. Roman Input Parameters: 5437a1cb98faSBarry Smith + dm - The `DMPLEX` object 5438ba2698f1SMatthew G. Knepley - cell - The cell 5439ba2698f1SMatthew G. Knepley 5440ba2698f1SMatthew G. Knepley Output Parameter: 5441ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5442ba2698f1SMatthew G. Knepley 5443ba2698f1SMatthew G. Knepley Level: intermediate 5444ba2698f1SMatthew G. Knepley 54451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5446ba2698f1SMatthew G. Knepley @*/ 5447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5448d71ae5a4SJacob Faibussowitsch { 54499f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5450ba2698f1SMatthew G. Knepley DMLabel label; 5451ba2698f1SMatthew G. Knepley PetscInt ct; 5452ba2698f1SMatthew G. Knepley 5453ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5454ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54554f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54569f4ada15SMatthew G. Knepley if (mesh->tr) { 54579f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54589f4ada15SMatthew G. Knepley } else { 545921027e53SStefano Zampini PetscInt pStart, pEnd; 546021027e53SStefano Zampini 546121027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 546221027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 546321027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 546421027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 546521027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 546621027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 546721027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 546821027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 546921027e53SStefano Zampini } 547021027e53SStefano Zampini } 547121027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 547221027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54749566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 547563a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5476936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 547721027e53SStefano Zampini } 54789f4ada15SMatthew G. Knepley } 54793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5480ba2698f1SMatthew G. Knepley } 5481ba2698f1SMatthew G. Knepley 5482412e9a14SMatthew G. Knepley /*@ 5483412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5484412e9a14SMatthew G. Knepley 5485412e9a14SMatthew G. Knepley Not Collective 5486412e9a14SMatthew G. Knepley 5487412e9a14SMatthew G. Knepley Input Parameters: 5488a1cb98faSBarry Smith + dm - The `DMPLEX` object 5489412e9a14SMatthew G. Knepley . cell - The cell 5490412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5491412e9a14SMatthew G. Knepley 5492a1cb98faSBarry Smith Level: advanced 5493a1cb98faSBarry Smith 5494a1cb98faSBarry Smith Note: 5495a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5496412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5497412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5498db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5499412e9a14SMatthew G. Knepley 55001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5501412e9a14SMatthew G. Knepley @*/ 5502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5503d71ae5a4SJacob Faibussowitsch { 550421027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5505412e9a14SMatthew G. Knepley DMLabel label; 550621027e53SStefano Zampini PetscInt pStart, pEnd; 5507412e9a14SMatthew G. Knepley 5508412e9a14SMatthew G. Knepley PetscFunctionBegin; 5509412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 551021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 55119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 55129566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 551321027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 551421027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 55153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5516412e9a14SMatthew G. Knepley } 5517412e9a14SMatthew G. Knepley 5518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5519d71ae5a4SJacob Faibussowitsch { 5520efe440bfSMatthew G. Knepley PetscSection section, s; 5521efe440bfSMatthew G. Knepley Mat m; 55223e922f36SToby Isaac PetscInt maxHeight; 5523dd4c3f67SMatthew G. Knepley const char *prefix; 5524552f7358SJed Brown 5525552f7358SJed Brown PetscFunctionBegin; 55269566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5527dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5528dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5529dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55309566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55319566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55329566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55339566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55349566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 55369566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 55379566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 55389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 55399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 55408f4c458bSMatthew G. Knepley 55419566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55429566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5543dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5544dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5546552f7358SJed Brown } 5547552f7358SJed Brown 5548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5549d71ae5a4SJacob Faibussowitsch { 55506858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55516858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5552f19dbd58SToby Isaac 5553f19dbd58SToby Isaac PetscFunctionBegin; 5554f19dbd58SToby Isaac *field = NULL; 55559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55576858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55586858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5559f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55606858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55616858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5562f19dbd58SToby Isaac } 55633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5564f19dbd58SToby Isaac } 5565f19dbd58SToby Isaac 55667cd05799SMatthew G. Knepley /*@C 55677cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55687cd05799SMatthew G. Knepley 55697cd05799SMatthew G. Knepley Not Collective 55707cd05799SMatthew G. Knepley 55712fe279fdSBarry Smith Input Parameter: 5572a1cb98faSBarry Smith . dm - The `DMPLEX` object 55737cd05799SMatthew G. Knepley 55747cd05799SMatthew G. Knepley Output Parameter: 5575a1cb98faSBarry Smith . section - The `PetscSection` object 55767cd05799SMatthew G. Knepley 55777cd05799SMatthew G. Knepley Level: developer 55787cd05799SMatthew G. Knepley 55791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55807cd05799SMatthew G. Knepley @*/ 5581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5582d71ae5a4SJacob Faibussowitsch { 5583552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5584552f7358SJed Brown 5585552f7358SJed Brown PetscFunctionBegin; 5586552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5587552f7358SJed Brown if (section) *section = mesh->coneSection; 55883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5589552f7358SJed Brown } 5590552f7358SJed Brown 55917cd05799SMatthew G. Knepley /*@C 55927cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55937cd05799SMatthew G. Knepley 55947cd05799SMatthew G. Knepley Not Collective 55957cd05799SMatthew G. Knepley 55962fe279fdSBarry Smith Input Parameter: 5597a1cb98faSBarry Smith . dm - The `DMPLEX` object 55987cd05799SMatthew G. Knepley 55997cd05799SMatthew G. Knepley Output Parameter: 5600a1cb98faSBarry Smith . section - The `PetscSection` object 56017cd05799SMatthew G. Knepley 56027cd05799SMatthew G. Knepley Level: developer 56037cd05799SMatthew G. Knepley 56041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 56057cd05799SMatthew G. Knepley @*/ 5606d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5607d71ae5a4SJacob Faibussowitsch { 56088cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 56098cb4d582SMatthew G. Knepley 56108cb4d582SMatthew G. Knepley PetscFunctionBegin; 56118cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56128cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 56133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56148cb4d582SMatthew G. Knepley } 56158cb4d582SMatthew G. Knepley 56167cd05799SMatthew G. Knepley /*@C 56177cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 56187cd05799SMatthew G. Knepley 56197cd05799SMatthew G. Knepley Not Collective 56207cd05799SMatthew G. Knepley 56212fe279fdSBarry Smith Input Parameter: 5622a1cb98faSBarry Smith . dm - The `DMPLEX` object 56237cd05799SMatthew G. Knepley 56247cd05799SMatthew G. Knepley Output Parameter: 56257cd05799SMatthew G. Knepley . cones - The cone for each point 56267cd05799SMatthew G. Knepley 56277cd05799SMatthew G. Knepley Level: developer 56287cd05799SMatthew G. Knepley 56291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56307cd05799SMatthew G. Knepley @*/ 5631d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5632d71ae5a4SJacob Faibussowitsch { 5633552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5634552f7358SJed Brown 5635552f7358SJed Brown PetscFunctionBegin; 5636552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5637552f7358SJed Brown if (cones) *cones = mesh->cones; 56383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5639552f7358SJed Brown } 5640552f7358SJed Brown 56417cd05799SMatthew G. Knepley /*@C 56427cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56437cd05799SMatthew G. Knepley 56447cd05799SMatthew G. Knepley Not Collective 56457cd05799SMatthew G. Knepley 56462fe279fdSBarry Smith Input Parameter: 5647a1cb98faSBarry Smith . dm - The `DMPLEX` object 56487cd05799SMatthew G. Knepley 56497cd05799SMatthew G. Knepley Output Parameter: 5650b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56517cd05799SMatthew G. Knepley 56527cd05799SMatthew G. Knepley Level: developer 56537cd05799SMatthew G. Knepley 5654b5a892a1SMatthew G. Knepley Notes: 5655a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5656b5a892a1SMatthew G. Knepley 5657a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5658b5a892a1SMatthew G. Knepley 56591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56607cd05799SMatthew G. Knepley @*/ 5661d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5662d71ae5a4SJacob Faibussowitsch { 5663552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5664552f7358SJed Brown 5665552f7358SJed Brown PetscFunctionBegin; 5666552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5667552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5669552f7358SJed Brown } 5670552f7358SJed Brown 5671552f7358SJed Brown /******************************** FEM Support **********************************/ 5672552f7358SJed Brown 5673d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5674d2b2dc1eSMatthew G. Knepley { 5675d2b2dc1eSMatthew G. Knepley PetscInt depth; 5676d2b2dc1eSMatthew G. Knepley 5677d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5678d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5679d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5680d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5681d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5682d2b2dc1eSMatthew G. Knepley } 5683d2b2dc1eSMatthew G. Knepley 56845962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56855962854dSMatthew G. Knepley { 56865962854dSMatthew G. Knepley PetscInt depth; 56875962854dSMatthew G. Knepley 56885962854dSMatthew G. Knepley PetscFunctionBegin; 56895962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56905962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56915962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56925962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56935962854dSMatthew G. Knepley } 56945962854dSMatthew G. Knepley 56959e8305c2SJed Brown /* 56969e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 56979e8305c2SJed Brown representing a line in the section. 56989e8305c2SJed Brown */ 56995f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5700d71ae5a4SJacob Faibussowitsch { 5701e327e467SRezgar Shakeri PetscObject obj; 5702e327e467SRezgar Shakeri PetscClassId id; 5703e327e467SRezgar Shakeri PetscFE fe = NULL; 5704e327e467SRezgar Shakeri 57059e8305c2SJed Brown PetscFunctionBeginHot; 57069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5707e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5708e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5709e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5710e327e467SRezgar Shakeri 5711e327e467SRezgar Shakeri if (!fe) { 5712e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 57139e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 57149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 57159e8305c2SJed Brown *k = *k / *Nc + 1; 5716e327e467SRezgar Shakeri } else { 5717e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 57185f82726aSMatthew G. Knepley PetscDualSpace dsp; 57195f82726aSMatthew G. Knepley 5720e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 57215f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 57225f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5723e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 57245f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 57255f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 57265f82726aSMatthew G. Knepley } 57275f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57285f82726aSMatthew G. Knepley } 57295f82726aSMatthew G. Knepley 57305f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 57315f82726aSMatthew G. Knepley { 57325f82726aSMatthew G. Knepley PetscFunctionBeginHot; 57335f82726aSMatthew G. Knepley if (tensor) { 57345f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 57355f82726aSMatthew G. Knepley } else { 57365f82726aSMatthew G. Knepley switch (dim) { 57375f82726aSMatthew G. Knepley case 1: 57385f82726aSMatthew G. Knepley *dof = k + 1; 57395f82726aSMatthew G. Knepley break; 57405f82726aSMatthew G. Knepley case 2: 57415f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 57425f82726aSMatthew G. Knepley break; 57435f82726aSMatthew G. Knepley case 3: 57445f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 57455f82726aSMatthew G. Knepley break; 57465f82726aSMatthew G. Knepley default: 57475f82726aSMatthew G. Knepley *dof = 0; 57485f82726aSMatthew G. Knepley } 57499e8305c2SJed Brown } 57503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57519e8305c2SJed Brown } 57529e8305c2SJed Brown 5753a4355906SMatthew Knepley /*@ 5754bc1eb3faSJed Brown 5755bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5756bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 575720f4b53cSBarry Smith section provided (or the section of the `DM`). 5758a4355906SMatthew Knepley 5759a4355906SMatthew Knepley Input Parameters: 576020f4b53cSBarry Smith + dm - The `DM` 576120f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 576220f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5763a4355906SMatthew Knepley 5764bc1eb3faSJed Brown Example: 5765bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5766bc1eb3faSJed Brown .vb 5767bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5768bc1eb3faSJed Brown 5769bc1eb3faSJed Brown v4 -- e6 -- v3 5770bc1eb3faSJed Brown | | 5771bc1eb3faSJed Brown e7 c0 e8 5772bc1eb3faSJed Brown | | 5773bc1eb3faSJed Brown v1 -- e5 -- v2 5774bc1eb3faSJed Brown .ve 5775bc1eb3faSJed Brown 5776bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5777bc1eb3faSJed Brown dofs in the order of points, e.g., 5778bc1eb3faSJed Brown .vb 5779bc1eb3faSJed Brown c0 -> [0,1,2,3] 5780bc1eb3faSJed Brown v1 -> [4] 5781bc1eb3faSJed Brown ... 5782bc1eb3faSJed Brown e5 -> [8, 9] 5783bc1eb3faSJed Brown .ve 5784bc1eb3faSJed Brown 5785bc1eb3faSJed Brown which corresponds to the dofs 5786bc1eb3faSJed Brown .vb 5787bc1eb3faSJed Brown 6 10 11 7 5788bc1eb3faSJed Brown 13 2 3 15 5789bc1eb3faSJed Brown 12 0 1 14 5790bc1eb3faSJed Brown 4 8 9 5 5791bc1eb3faSJed Brown .ve 5792bc1eb3faSJed Brown 5793bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5794bc1eb3faSJed Brown .vb 5795bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5796bc1eb3faSJed Brown .ve 5797bc1eb3faSJed Brown 5798bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5799bc1eb3faSJed Brown .vb 5800bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5801bc1eb3faSJed Brown .ve 5802bc1eb3faSJed Brown 5803a4355906SMatthew Knepley Level: developer 5804a4355906SMatthew Knepley 5805da9ac489SAlbert Cowie Notes: 5806a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5807a1cb98faSBarry Smith degree of the basis. 5808a1cb98faSBarry Smith 5809da9ac489SAlbert Cowie This is required to run with libCEED. 5810da9ac489SAlbert Cowie 58111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5812a4355906SMatthew Knepley @*/ 5813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5814d71ae5a4SJacob Faibussowitsch { 58157391a63aSMatthew G. Knepley DMLabel label; 5816bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 58175f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 58183194fc30SMatthew G. Knepley 58193194fc30SMatthew G. Knepley PetscFunctionBegin; 58209566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 58213ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5822a433471fSStefano Zampini if (point < 0) { 5823a433471fSStefano Zampini PetscInt sStart, sEnd; 5824a433471fSStefano Zampini 58259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5826a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5827a433471fSStefano Zampini } 58289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 58299566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 58309566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58319371c9d4SSatish Balay if (depth == 1) { 58329371c9d4SSatish Balay eStart = point; 58339371c9d4SSatish Balay } else if (depth == dim) { 58347391a63aSMatthew G. Knepley const PetscInt *cone; 58357391a63aSMatthew G. Knepley 58369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5837d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5838d4e6627bSStefano Zampini else if (dim == 3) { 5839d4e6627bSStefano Zampini const PetscInt *cone2; 58409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5841d4e6627bSStefano Zampini eStart = cone2[0]; 584263a3b9bcSJacob 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); 584363a3b9bcSJacob 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); 5844e327e467SRezgar Shakeri 58459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5846bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5847bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5848bb197d40SJed Brown PetscInt *perm; 5849bb197d40SJed Brown 58503194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 58515f82726aSMatthew G. Knepley PetscInt dof; 58525f82726aSMatthew G. Knepley 58535f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58545f82726aSMatthew G. Knepley PetscCheck(dim == 1 || tensor || !continuous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Continuous field %" PetscInt_FMT " must have a tensor product discretization", f); 58555f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58565f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58575f82726aSMatthew G. Knepley size += dof * Nc; 58583194fc30SMatthew G. Knepley } 58599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58603194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5861bb197d40SJed Brown switch (d) { 5862babf31e0SJed Brown case 1: 58635f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58645f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5865babf31e0SJed Brown /* 5866babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5867babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5868babf31e0SJed Brown */ 5869e327e467SRezgar Shakeri if (continuous) { 5870babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58719371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58729371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5873babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5874babf31e0SJed Brown foffset = offset; 5875e327e467SRezgar Shakeri } else { 58765f82726aSMatthew G. Knepley PetscInt dof; 58775f82726aSMatthew G. Knepley 58785f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58795f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 58805f82726aSMatthew G. Knepley foffset = offset; 5881e327e467SRezgar Shakeri } 5882babf31e0SJed Brown break; 588389eabcffSMatthew G. Knepley case 2: 58843194fc30SMatthew 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} */ 58855f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58865f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58873194fc30SMatthew G. Knepley /* The SEM order is 58883194fc30SMatthew G. Knepley 58893194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 589089eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58913194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58923194fc30SMatthew G. Knepley */ 5893e327e467SRezgar Shakeri if (continuous) { 58943194fc30SMatthew G. Knepley const PetscInt of = 0; 58953194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 58963194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 58973194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 58983194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 58993194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 59003194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 59013194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 59023194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 59033194fc30SMatthew G. Knepley PetscInt o; 59043194fc30SMatthew G. Knepley 59053194fc30SMatthew G. Knepley /* bottom */ 59063194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 59079371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 59089371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59093194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 59103194fc30SMatthew G. Knepley /* middle */ 59113194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 59123194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 59139371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 59149371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59153194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 59163194fc30SMatthew G. Knepley } 59173194fc30SMatthew G. Knepley /* top */ 59183194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 59199371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 59209371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59213194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 59223194fc30SMatthew G. Knepley foffset = offset; 5923e327e467SRezgar Shakeri } else { 59245f82726aSMatthew G. Knepley PetscInt dof; 59255f82726aSMatthew G. Knepley 59265f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59275f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 59285f82726aSMatthew G. Knepley foffset = offset; 59293194fc30SMatthew G. Knepley } 593089eabcffSMatthew G. Knepley break; 593189eabcffSMatthew G. Knepley case 3: 593289eabcffSMatthew G. Knepley /* The original hex closure is 593389eabcffSMatthew G. Knepley 593489eabcffSMatthew G. Knepley {c, 593589eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 593689eabcffSMatthew 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, 593789eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 593889eabcffSMatthew G. Knepley */ 59395f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59405f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 594189eabcffSMatthew G. Knepley /* The SEM order is 594289eabcffSMatthew G. Knepley Bottom Slice 594389eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 594489eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 594589eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 594689eabcffSMatthew G. Knepley 594789eabcffSMatthew G. Knepley Middle Slice (j) 594889eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 594989eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 595089eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 595189eabcffSMatthew G. Knepley 595289eabcffSMatthew G. Knepley Top Slice 595389eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 595489eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 595589eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 595689eabcffSMatthew G. Knepley */ 5957e327e467SRezgar Shakeri if (continuous) { 595889eabcffSMatthew G. Knepley const PetscInt oc = 0; 595989eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 596089eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 596189eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 596289eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 596389eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 596489eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 596589eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 596689eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 596789eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 596889eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 596989eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 597089eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 597189eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 597289eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 597389eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 597489eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 597589eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 597689eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 597789eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 597889eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 597989eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 598089eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 598189eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 598289eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 598389eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 598489eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 598589eabcffSMatthew G. Knepley PetscInt o, n; 598689eabcffSMatthew G. Knepley 598789eabcffSMatthew G. Knepley /* Bottom Slice */ 598889eabcffSMatthew G. Knepley /* bottom */ 598989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59909371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59919371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 599289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 599389eabcffSMatthew G. Knepley /* middle */ 599489eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 599589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 59969371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 59979371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 59989371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59999371c9d4SSatish Balay } 600089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 60013194fc30SMatthew G. Knepley } 600289eabcffSMatthew G. Knepley /* top */ 600389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 60049371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 60059371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 600689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 600789eabcffSMatthew G. Knepley 600889eabcffSMatthew G. Knepley /* Middle Slice */ 600989eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 601089eabcffSMatthew G. Knepley /* bottom */ 601189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 60129371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 60139371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 601589eabcffSMatthew G. Knepley /* middle */ 601689eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 601789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 60189371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60199371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 602089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 602189eabcffSMatthew G. Knepley } 602289eabcffSMatthew G. Knepley /* top */ 602389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 60249371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 60259371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 602689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 602789eabcffSMatthew G. Knepley } 602889eabcffSMatthew G. Knepley 602989eabcffSMatthew G. Knepley /* Top Slice */ 603089eabcffSMatthew G. Knepley /* bottom */ 603189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 60329371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 60339371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 603589eabcffSMatthew G. Knepley /* middle */ 603689eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 603789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 60389371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60399371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 604089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 604189eabcffSMatthew G. Knepley } 604289eabcffSMatthew G. Knepley /* top */ 604389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 60449371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 60459371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 604689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 604789eabcffSMatthew G. Knepley 604889eabcffSMatthew G. Knepley foffset = offset; 6049e327e467SRezgar Shakeri } else { 60505f82726aSMatthew G. Knepley PetscInt dof; 60515f82726aSMatthew G. Knepley 60525f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60535f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60545f82726aSMatthew G. Knepley foffset = offset; 605589eabcffSMatthew G. Knepley } 605689eabcffSMatthew G. Knepley break; 6057d71ae5a4SJacob Faibussowitsch default: 6058d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 605989eabcffSMatthew G. Knepley } 606089eabcffSMatthew G. Knepley } 606163a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 60623194fc30SMatthew G. Knepley /* Check permutation */ 60633194fc30SMatthew G. Knepley { 60643194fc30SMatthew G. Knepley PetscInt *check; 60653194fc30SMatthew G. Knepley 60669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 60671dca8a05SBarry Smith for (i = 0; i < size; ++i) { 60681dca8a05SBarry Smith check[i] = -1; 60691dca8a05SBarry 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]); 60701dca8a05SBarry Smith } 60713194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60721dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60739566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60743194fc30SMatthew G. Knepley } 60759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6076a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6077a05c9aa3SJed Brown PetscInt *loc_perm; 60789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6079a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6080a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6081a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6082a05c9aa3SJed Brown } 60839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6084a05c9aa3SJed Brown } 6085bb197d40SJed Brown } 60863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60873194fc30SMatthew G. Knepley } 60883194fc30SMatthew G. Knepley 6089d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6090d71ae5a4SJacob Faibussowitsch { 6091e071409bSToby Isaac PetscDS prob; 6092e071409bSToby Isaac PetscInt depth, Nf, h; 6093e071409bSToby Isaac DMLabel label; 6094e071409bSToby Isaac 6095e071409bSToby Isaac PetscFunctionBeginHot; 60969566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6097e071409bSToby Isaac Nf = prob->Nf; 6098e071409bSToby Isaac label = dm->depthLabel; 6099e071409bSToby Isaac *dspace = NULL; 6100e071409bSToby Isaac if (field < Nf) { 6101e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6102e071409bSToby Isaac 6103e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6104e071409bSToby Isaac PetscDualSpace dsp; 6105e071409bSToby Isaac 61069566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 61079566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 61089566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6109e071409bSToby Isaac h = depth - 1 - h; 6110e071409bSToby Isaac if (h) { 61119566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6112e071409bSToby Isaac } else { 6113e071409bSToby Isaac *dspace = dsp; 6114e071409bSToby Isaac } 6115e071409bSToby Isaac } 6116e071409bSToby Isaac } 61173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6118e071409bSToby Isaac } 6119e071409bSToby Isaac 6120d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6121d71ae5a4SJacob Faibussowitsch { 612228351e22SJed Brown PetscScalar *array; 612328351e22SJed Brown const PetscScalar *vArray; 6124d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 61251a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6126552f7358SJed Brown 61271b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61299566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61323f7cbbe7SMatthew G. Knepley if (!values || !*values) { 61339df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61349df71ca4SMatthew G. Knepley PetscInt dof; 6135d9917b9dSMatthew G. Knepley 61369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61379df71ca4SMatthew G. Knepley size += dof; 61389df71ca4SMatthew G. Knepley } 61399df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61409df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61412a3aaacfSMatthew G. Knepley PetscInt dof; 61425a1bb5cfSMatthew G. Knepley 61435a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61455a1bb5cfSMatthew G. Knepley size += dof; 61465a1bb5cfSMatthew G. Knepley } 61473f7cbbe7SMatthew G. Knepley if (!values) { 61483f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 61493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61503f7cbbe7SMatthew G. Knepley } 61519566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6152982e9ed1SMatthew G. Knepley } else { 6153982e9ed1SMatthew G. Knepley array = *values; 6154982e9ed1SMatthew G. Knepley } 61559df71ca4SMatthew G. Knepley size = 0; 615628351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 61579df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61589df71ca4SMatthew G. Knepley PetscInt dof, off, d; 615928351e22SJed Brown const PetscScalar *varr; 6160d9917b9dSMatthew G. Knepley 61619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61638e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6164ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61659df71ca4SMatthew G. Knepley size += dof; 61669df71ca4SMatthew G. Knepley } 61679df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61689df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61699df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61705a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 617128351e22SJed Brown const PetscScalar *varr; 61725a1bb5cfSMatthew G. Knepley 617352ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61768e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 61775a1bb5cfSMatthew G. Knepley if (o >= 0) { 6178ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61795a1bb5cfSMatthew G. Knepley } else { 6180ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61815a1bb5cfSMatthew G. Knepley } 61829df71ca4SMatthew G. Knepley size += dof; 61835a1bb5cfSMatthew G. Knepley } 618428351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61859df71ca4SMatthew G. Knepley if (!*values) { 61865a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61875a1bb5cfSMatthew G. Knepley *values = array; 61889df71ca4SMatthew G. Knepley } else { 618963a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61908c312ff3SMatthew G. Knepley *csize = size; 61919df71ca4SMatthew G. Knepley } 61923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61935a1bb5cfSMatthew G. Knepley } 6194d9917b9dSMatthew G. Knepley 619527f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6196d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6197d71ae5a4SJacob Faibussowitsch { 619827f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 619927f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 620027f02ce8SMatthew G. Knepley 62019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 620227f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 620327f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 620427f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 620527f02ce8SMatthew G. Knepley points[q * 2] = r; 620627f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 620727f02ce8SMatthew G. Knepley ++q; 620827f02ce8SMatthew G. Knepley } 620927f02ce8SMatthew G. Knepley } 621027f02ce8SMatthew G. Knepley *numPoints = q; 62113ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 621227f02ce8SMatthew G. Knepley } 621327f02ce8SMatthew G. Knepley 621497529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 621507218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6216d71ae5a4SJacob Faibussowitsch { 621727f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6218923c78e0SToby Isaac PetscInt np, *pts = NULL; 6219923c78e0SToby Isaac 6220923c78e0SToby Isaac PetscFunctionBeginHot; 62219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 622207218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6223923c78e0SToby Isaac PetscInt dof, off; 6224923c78e0SToby Isaac 62259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 62269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 62279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6228923c78e0SToby Isaac np = dof / 2; 62298e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 623027f02ce8SMatthew G. Knepley } else { 623107218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 62329566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6233923c78e0SToby Isaac } 6234923c78e0SToby Isaac *numPoints = np; 6235923c78e0SToby Isaac *points = pts; 6236923c78e0SToby Isaac *clp = cla; 62373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6238923c78e0SToby Isaac } 6239923c78e0SToby Isaac 6240d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6241d71ae5a4SJacob Faibussowitsch { 6242923c78e0SToby Isaac PetscFunctionBeginHot; 6243923c78e0SToby Isaac if (!*clPoints) { 62449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6245923c78e0SToby Isaac } else { 62469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6247923c78e0SToby Isaac } 6248923c78e0SToby Isaac *numPoints = 0; 6249923c78e0SToby Isaac *points = NULL; 6250923c78e0SToby Isaac *clSec = NULL; 6251923c78e0SToby Isaac *clPoints = NULL; 6252923c78e0SToby Isaac *clp = NULL; 62533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6254923c78e0SToby Isaac } 6255923c78e0SToby Isaac 6256d71ae5a4SJacob 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[]) 6257d71ae5a4SJacob Faibussowitsch { 62581a271a75SMatthew G. Knepley PetscInt offset = 0, p; 625997e99dd9SToby Isaac const PetscInt **perms = NULL; 626097e99dd9SToby Isaac const PetscScalar **flips = NULL; 62611a271a75SMatthew G. Knepley 62621a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6263fe02ba77SJed Brown *size = 0; 62649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 626597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 626697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 626797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 626897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62691a271a75SMatthew G. Knepley PetscInt dof, off, d; 62701a271a75SMatthew G. Knepley const PetscScalar *varr; 62711a271a75SMatthew G. Knepley 62729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62748e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 627597e99dd9SToby Isaac if (clperm) { 627697e99dd9SToby Isaac if (perm) { 627797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62781a271a75SMatthew G. Knepley } else { 627997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 628097e99dd9SToby Isaac } 628197e99dd9SToby Isaac if (flip) { 628297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 628397e99dd9SToby Isaac } 628497e99dd9SToby Isaac } else { 628597e99dd9SToby Isaac if (perm) { 628697e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 628797e99dd9SToby Isaac } else { 628897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 628997e99dd9SToby Isaac } 629097e99dd9SToby Isaac if (flip) { 629197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62921a271a75SMatthew G. Knepley } 62931a271a75SMatthew G. Knepley } 629497e99dd9SToby Isaac offset += dof; 629597e99dd9SToby Isaac } 62969566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 62971a271a75SMatthew G. Knepley *size = offset; 62983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62991a271a75SMatthew G. Knepley } 63001a271a75SMatthew G. Knepley 6301d71ae5a4SJacob 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[]) 6302d71ae5a4SJacob Faibussowitsch { 63031a271a75SMatthew G. Knepley PetscInt offset = 0, f; 63041a271a75SMatthew G. Knepley 63051a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6306fe02ba77SJed Brown *size = 0; 63071a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 630897e99dd9SToby Isaac PetscInt p; 630997e99dd9SToby Isaac const PetscInt **perms = NULL; 631097e99dd9SToby Isaac const PetscScalar **flips = NULL; 63111a271a75SMatthew G. Knepley 63129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 631397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 631497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 631597e99dd9SToby Isaac PetscInt fdof, foff, b; 63161a271a75SMatthew G. Knepley const PetscScalar *varr; 631797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 631897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63191a271a75SMatthew G. Knepley 63209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63221a271a75SMatthew G. Knepley varr = &vArray[foff]; 632397e99dd9SToby Isaac if (clperm) { 63249371c9d4SSatish Balay if (perm) { 6325ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 63261a271a75SMatthew G. Knepley } else { 6327ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 63289371c9d4SSatish Balay } 63299371c9d4SSatish Balay if (flip) { 6330ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 63319371c9d4SSatish Balay } 63329371c9d4SSatish Balay } else { 63339371c9d4SSatish Balay if (perm) { 6334ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 63359371c9d4SSatish Balay } else { 6336ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 63379371c9d4SSatish Balay } 63389371c9d4SSatish Balay if (flip) { 6339ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 63409371c9d4SSatish Balay } 63411a271a75SMatthew G. Knepley } 634297e99dd9SToby Isaac offset += fdof; 63431a271a75SMatthew G. Knepley } 63449566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63451a271a75SMatthew G. Knepley } 63461a271a75SMatthew G. Knepley *size = offset; 63473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63481a271a75SMatthew G. Knepley } 63491a271a75SMatthew G. Knepley 6350e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 635107218a29SMatthew G. Knepley { 635207218a29SMatthew G. Knepley PetscSection clSection; 635307218a29SMatthew G. Knepley IS clPoints; 635407218a29SMatthew G. Knepley PetscInt *points = NULL; 6355e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 635607218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 635707218a29SMatthew G. Knepley 635807218a29SMatthew G. Knepley PetscFunctionBeginHot; 635907218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 636007218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 636107218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6362e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 636307218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 636407218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 636507218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 636607218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 636707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 636807218a29SMatthew G. Knepley } 636907218a29SMatthew G. Knepley /* Get points */ 637007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 637107218a29SMatthew G. Knepley /* Get sizes */ 637207218a29SMatthew G. Knepley asize = 0; 637307218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 637407218a29SMatthew G. Knepley PetscInt dof; 637507218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 637607218a29SMatthew G. Knepley asize += dof; 637707218a29SMatthew G. Knepley } 637807218a29SMatthew G. Knepley if (values) { 637907218a29SMatthew G. Knepley const PetscScalar *vArray; 638007218a29SMatthew G. Knepley PetscInt size; 638107218a29SMatthew G. Knepley 638207218a29SMatthew G. Knepley if (*values) { 638307218a29SMatthew 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); 638407218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6385e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 638607218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 638707218a29SMatthew G. Knepley /* Get values */ 638807218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 638907218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 639007218a29SMatthew 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); 639107218a29SMatthew G. Knepley /* Cleanup array */ 639207218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 639307218a29SMatthew G. Knepley } 639407218a29SMatthew G. Knepley if (csize) *csize = asize; 639507218a29SMatthew G. Knepley /* Cleanup points */ 639607218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 639707218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 639807218a29SMatthew G. Knepley } 639907218a29SMatthew G. Knepley 6400552f7358SJed Brown /*@C 6401552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6402552f7358SJed Brown 6403552f7358SJed Brown Not collective 6404552f7358SJed Brown 6405552f7358SJed Brown Input Parameters: 6406a1cb98faSBarry Smith + dm - The `DM` 640720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6408552f7358SJed Brown . v - The local vector 6409a1cb98faSBarry Smith - point - The point in the `DM` 6410552f7358SJed Brown 64116b867d5aSJose E. Roman Input/Output Parameters: 641220f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 641320f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 641420f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 641522c1ee49SMatthew G. Knepley 6416552f7358SJed Brown Level: intermediate 6417552f7358SJed Brown 6418a1cb98faSBarry Smith Notes: 641920f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6420a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6421a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6422a1cb98faSBarry Smith 6423a1cb98faSBarry Smith A typical use could be 6424a1cb98faSBarry Smith .vb 6425a1cb98faSBarry Smith values = NULL; 6426a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6427a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6428a1cb98faSBarry Smith <Compute on closure> 6429a1cb98faSBarry Smith } 6430a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6431a1cb98faSBarry Smith .ve 6432a1cb98faSBarry Smith or 6433a1cb98faSBarry Smith .vb 6434a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6435a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6436a1cb98faSBarry Smith clSize = clMaxSize; 6437a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6438a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6439a1cb98faSBarry Smith <Compute on closure> 6440a1cb98faSBarry Smith } 6441a1cb98faSBarry Smith } 6442a1cb98faSBarry Smith PetscFree(values); 6443a1cb98faSBarry Smith .ve 6444a1cb98faSBarry Smith 644560225df5SJacob Faibussowitsch Fortran Notes: 644620f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6447a1cb98faSBarry Smith 64481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6449552f7358SJed Brown @*/ 6450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6451d71ae5a4SJacob Faibussowitsch { 6452d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6453e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 64543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6455552f7358SJed Brown } 6456552f7358SJed Brown 6457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6458d71ae5a4SJacob Faibussowitsch { 6459e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6460e5c487bfSMatthew G. Knepley PetscSection clSection; 6461e5c487bfSMatthew G. Knepley IS clPoints; 6462e5c487bfSMatthew G. Knepley PetscScalar *array; 6463e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6464e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6465c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6466c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6467e5c487bfSMatthew G. Knepley 6468e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6469e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64709566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6471e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6472e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6476e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64779566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6479e5c487bfSMatthew G. Knepley } 6480e5c487bfSMatthew G. Knepley /* Get points */ 648107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6482c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6483c459fbc1SJed Brown PetscInt dof; 64849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6485c459fbc1SJed Brown clsize += dof; 6486c459fbc1SJed Brown } 64879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6488e5c487bfSMatthew G. Knepley /* Filter points */ 6489e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6490e5c487bfSMatthew G. Knepley PetscInt dep; 6491e5c487bfSMatthew G. Knepley 64929566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6493e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6494e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6495e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6496e5c487bfSMatthew G. Knepley ++Np; 6497e5c487bfSMatthew G. Knepley } 6498e5c487bfSMatthew G. Knepley /* Get array */ 6499e5c487bfSMatthew G. Knepley if (!values || !*values) { 6500e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6501e5c487bfSMatthew G. Knepley 6502e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 65039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6504e5c487bfSMatthew G. Knepley asize += dof; 6505e5c487bfSMatthew G. Knepley } 6506e5c487bfSMatthew G. Knepley if (!values) { 65079566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6508e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 65093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6510e5c487bfSMatthew G. Knepley } 65119566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6512e5c487bfSMatthew G. Knepley } else { 6513e5c487bfSMatthew G. Knepley array = *values; 6514e5c487bfSMatthew G. Knepley } 65159566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6516e5c487bfSMatthew G. Knepley /* Get values */ 65179566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 65189566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6519e5c487bfSMatthew G. Knepley /* Cleanup points */ 65209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6521e5c487bfSMatthew G. Knepley /* Cleanup array */ 65229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6523e5c487bfSMatthew G. Knepley if (!*values) { 6524e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6525e5c487bfSMatthew G. Knepley *values = array; 6526e5c487bfSMatthew G. Knepley } else { 652763a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6528e5c487bfSMatthew G. Knepley *csize = size; 6529e5c487bfSMatthew G. Knepley } 65303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6531e5c487bfSMatthew G. Knepley } 6532e5c487bfSMatthew G. Knepley 6533552f7358SJed Brown /*@C 6534552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6535552f7358SJed Brown 6536552f7358SJed Brown Not collective 6537552f7358SJed Brown 6538552f7358SJed Brown Input Parameters: 6539a1cb98faSBarry Smith + dm - The `DM` 654020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6541552f7358SJed Brown . v - The local vector 6542a1cb98faSBarry Smith . point - The point in the `DM` 654320f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6544552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6545552f7358SJed Brown 6546552f7358SJed Brown Level: intermediate 6547552f7358SJed Brown 6548a1cb98faSBarry Smith Note: 654920f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6550a1cb98faSBarry Smith 655160225df5SJacob Faibussowitsch Fortran Notes: 655220f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6553a1cb98faSBarry Smith 65541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6555552f7358SJed Brown @*/ 6556d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6557d71ae5a4SJacob Faibussowitsch { 6558552f7358SJed Brown PetscInt size = 0; 6559552f7358SJed Brown 6560552f7358SJed Brown PetscFunctionBegin; 6561552f7358SJed Brown /* Should work without recalculating size */ 65629566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6563c9fdaa05SMatthew G. Knepley *values = NULL; 65643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6565552f7358SJed Brown } 6566552f7358SJed Brown 6567d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6568d71ae5a4SJacob Faibussowitsch { 65699371c9d4SSatish Balay *x += y; 65709371c9d4SSatish Balay } 6571d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6572d71ae5a4SJacob Faibussowitsch { 65739371c9d4SSatish Balay *x = y; 65749371c9d4SSatish Balay } 6575552f7358SJed Brown 6576d71ae5a4SJacob 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[]) 6577d71ae5a4SJacob Faibussowitsch { 6578552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6579552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6580552f7358SJed Brown PetscScalar *a; 6581552f7358SJed Brown PetscInt off, cind = 0, k; 6582552f7358SJed Brown 6583552f7358SJed Brown PetscFunctionBegin; 65849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6586552f7358SJed Brown a = &array[off]; 6587552f7358SJed Brown if (!cdof || setBC) { 658897e99dd9SToby Isaac if (clperm) { 65899371c9d4SSatish Balay if (perm) { 6590ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6591552f7358SJed Brown } else { 6592ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 65939371c9d4SSatish Balay } 65949371c9d4SSatish Balay } else { 65959371c9d4SSatish Balay if (perm) { 6596ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 65979371c9d4SSatish Balay } else { 6598ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 65999371c9d4SSatish Balay } 6600552f7358SJed Brown } 6601552f7358SJed Brown } else { 66029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 660397e99dd9SToby Isaac if (clperm) { 66049371c9d4SSatish Balay if (perm) { 66059371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 66069371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66079371c9d4SSatish Balay ++cind; 66089371c9d4SSatish Balay continue; 66099371c9d4SSatish Balay } 661097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6611552f7358SJed Brown } 6612552f7358SJed Brown } else { 6613552f7358SJed Brown for (k = 0; k < dof; ++k) { 66149371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66159371c9d4SSatish Balay ++cind; 66169371c9d4SSatish Balay continue; 66179371c9d4SSatish Balay } 661897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 661997e99dd9SToby Isaac } 662097e99dd9SToby Isaac } 662197e99dd9SToby Isaac } else { 662297e99dd9SToby Isaac if (perm) { 662397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66249371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66259371c9d4SSatish Balay ++cind; 66269371c9d4SSatish Balay continue; 66279371c9d4SSatish Balay } 662897e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 662997e99dd9SToby Isaac } 663097e99dd9SToby Isaac } else { 663197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66329371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66339371c9d4SSatish Balay ++cind; 66349371c9d4SSatish Balay continue; 66359371c9d4SSatish Balay } 663697e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 663797e99dd9SToby Isaac } 6638552f7358SJed Brown } 6639552f7358SJed Brown } 6640552f7358SJed Brown } 66413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6642552f7358SJed Brown } 6643552f7358SJed Brown 6644d71ae5a4SJacob 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[]) 6645d71ae5a4SJacob Faibussowitsch { 6646a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6647a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6648a5e93ea8SMatthew G. Knepley PetscScalar *a; 6649a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6650a5e93ea8SMatthew G. Knepley 6651a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 66539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6654a5e93ea8SMatthew G. Knepley a = &array[off]; 6655a5e93ea8SMatthew G. Knepley if (cdof) { 66569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 665797e99dd9SToby Isaac if (clperm) { 665897e99dd9SToby Isaac if (perm) { 6659a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6660a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 666297e99dd9SToby Isaac cind++; 6663a5e93ea8SMatthew G. Knepley } 6664a5e93ea8SMatthew G. Knepley } 6665a5e93ea8SMatthew G. Knepley } else { 6666a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6667a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666897e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 666997e99dd9SToby Isaac cind++; 667097e99dd9SToby Isaac } 667197e99dd9SToby Isaac } 667297e99dd9SToby Isaac } 667397e99dd9SToby Isaac } else { 667497e99dd9SToby Isaac if (perm) { 667597e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 667697e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 667797e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 667897e99dd9SToby Isaac cind++; 667997e99dd9SToby Isaac } 668097e99dd9SToby Isaac } 668197e99dd9SToby Isaac } else { 668297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668397e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668497e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 668597e99dd9SToby Isaac cind++; 668697e99dd9SToby Isaac } 6687a5e93ea8SMatthew G. Knepley } 6688a5e93ea8SMatthew G. Knepley } 6689a5e93ea8SMatthew G. Knepley } 6690a5e93ea8SMatthew G. Knepley } 66913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6692a5e93ea8SMatthew G. Knepley } 6693a5e93ea8SMatthew G. Knepley 6694d71ae5a4SJacob 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[]) 6695d71ae5a4SJacob Faibussowitsch { 6696552f7358SJed Brown PetscScalar *a; 66971a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 66981a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 669997e99dd9SToby Isaac PetscInt cind = 0, b; 6700552f7358SJed Brown 6701552f7358SJed Brown PetscFunctionBegin; 67029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67051a271a75SMatthew G. Knepley a = &array[foff]; 6706552f7358SJed Brown if (!fcdof || setBC) { 670797e99dd9SToby Isaac if (clperm) { 67089371c9d4SSatish Balay if (perm) { 6709ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6710552f7358SJed Brown } else { 6711ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 67129371c9d4SSatish Balay } 67139371c9d4SSatish Balay } else { 67149371c9d4SSatish Balay if (perm) { 6715ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 67169371c9d4SSatish Balay } else { 6717ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 67189371c9d4SSatish Balay } 6719552f7358SJed Brown } 6720552f7358SJed Brown } else { 67219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672297e99dd9SToby Isaac if (clperm) { 672397e99dd9SToby Isaac if (perm) { 672497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67259371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67269371c9d4SSatish Balay ++cind; 67279371c9d4SSatish Balay continue; 67289371c9d4SSatish Balay } 672997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6730552f7358SJed Brown } 6731552f7358SJed Brown } else { 673297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67339371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67349371c9d4SSatish Balay ++cind; 67359371c9d4SSatish Balay continue; 67369371c9d4SSatish Balay } 673797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 673897e99dd9SToby Isaac } 673997e99dd9SToby Isaac } 674097e99dd9SToby Isaac } else { 674197e99dd9SToby Isaac if (perm) { 674297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67439371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67449371c9d4SSatish Balay ++cind; 67459371c9d4SSatish Balay continue; 67469371c9d4SSatish Balay } 674797e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 674897e99dd9SToby Isaac } 674997e99dd9SToby Isaac } else { 675097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67519371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67529371c9d4SSatish Balay ++cind; 67539371c9d4SSatish Balay continue; 67549371c9d4SSatish Balay } 675597e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6756552f7358SJed Brown } 6757552f7358SJed Brown } 6758552f7358SJed Brown } 6759552f7358SJed Brown } 67601a271a75SMatthew G. Knepley *offset += fdof; 67613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6762552f7358SJed Brown } 6763552f7358SJed Brown 6764d71ae5a4SJacob 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[]) 6765d71ae5a4SJacob Faibussowitsch { 6766a5e93ea8SMatthew G. Knepley PetscScalar *a; 67671a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67681a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67695da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6770ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6771a5e93ea8SMatthew G. Knepley 6772a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67771a271a75SMatthew G. Knepley a = &array[foff]; 6778a5e93ea8SMatthew G. Knepley if (fcdof) { 6779ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 678197e99dd9SToby Isaac if (clperm) { 678297e99dd9SToby Isaac if (perm) { 6783ba322698SMatthew G. Knepley if (comps) { 6784ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6785ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67869371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67879371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67889371c9d4SSatish Balay ncSet = PETSC_TRUE; 67899371c9d4SSatish Balay } 67909371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67919371c9d4SSatish Balay ++cind; 67929371c9d4SSatish Balay fcSet = PETSC_TRUE; 67939371c9d4SSatish Balay } 6794ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6795ba322698SMatthew G. Knepley } 6796ba322698SMatthew G. Knepley } else { 679797e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 679897e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 679997e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6800a5e93ea8SMatthew G. Knepley ++cind; 6801a5e93ea8SMatthew G. Knepley } 6802a5e93ea8SMatthew G. Knepley } 6803ba322698SMatthew G. Knepley } 6804ba322698SMatthew G. Knepley } else { 6805ba322698SMatthew G. Knepley if (comps) { 6806ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6807ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68089371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68099371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68109371c9d4SSatish Balay ncSet = PETSC_TRUE; 68119371c9d4SSatish Balay } 68129371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68139371c9d4SSatish Balay ++cind; 68149371c9d4SSatish Balay fcSet = PETSC_TRUE; 68159371c9d4SSatish Balay } 6816ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6817ba322698SMatthew G. Knepley } 6818a5e93ea8SMatthew G. Knepley } else { 681997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 682097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 682197e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 682297e99dd9SToby Isaac ++cind; 682397e99dd9SToby Isaac } 682497e99dd9SToby Isaac } 682597e99dd9SToby Isaac } 6826ba322698SMatthew G. Knepley } 682797e99dd9SToby Isaac } else { 682897e99dd9SToby Isaac if (perm) { 6829ba322698SMatthew G. Knepley if (comps) { 6830ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6831ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68329371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68339371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68349371c9d4SSatish Balay ncSet = PETSC_TRUE; 68359371c9d4SSatish Balay } 68369371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68379371c9d4SSatish Balay ++cind; 68389371c9d4SSatish Balay fcSet = PETSC_TRUE; 68399371c9d4SSatish Balay } 6840ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6841ba322698SMatthew G. Knepley } 6842ba322698SMatthew G. Knepley } else { 684397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 684497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 684597e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 684697e99dd9SToby Isaac ++cind; 684797e99dd9SToby Isaac } 684897e99dd9SToby Isaac } 6849ba322698SMatthew G. Knepley } 6850ba322698SMatthew G. Knepley } else { 6851ba322698SMatthew G. Knepley if (comps) { 6852ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6853ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68549371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68559371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68569371c9d4SSatish Balay ncSet = PETSC_TRUE; 68579371c9d4SSatish Balay } 68589371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68599371c9d4SSatish Balay ++cind; 68609371c9d4SSatish Balay fcSet = PETSC_TRUE; 68619371c9d4SSatish Balay } 6862ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6863ba322698SMatthew G. Knepley } 686497e99dd9SToby Isaac } else { 686597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 686697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 686797e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6868a5e93ea8SMatthew G. Knepley ++cind; 6869a5e93ea8SMatthew G. Knepley } 6870a5e93ea8SMatthew G. Knepley } 6871a5e93ea8SMatthew G. Knepley } 6872a5e93ea8SMatthew G. Knepley } 6873a5e93ea8SMatthew G. Knepley } 6874ba322698SMatthew G. Knepley } 68751a271a75SMatthew G. Knepley *offset += fdof; 68763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6877a5e93ea8SMatthew G. Knepley } 6878a5e93ea8SMatthew G. Knepley 6879d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6880d71ae5a4SJacob Faibussowitsch { 6881552f7358SJed Brown PetscScalar *array; 68821b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68831b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6884552f7358SJed Brown 68851b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68879566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68899566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68909566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6891b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6892b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6893b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6894b6ebb6e6SMatthew G. Knepley 68959371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 68969371c9d4SSatish Balay dof = 0; 68979371c9d4SSatish Balay continue; 68989371c9d4SSatish Balay } 68999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6900b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6901b6ebb6e6SMatthew G. Knepley { 6902b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6903b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6904b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6905b6ebb6e6SMatthew G. Knepley 69069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 69079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6908b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6909b6ebb6e6SMatthew G. Knepley if (!cdof) { 6910b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6911ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6912b6ebb6e6SMatthew G. Knepley } else { 6913ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6914b6ebb6e6SMatthew G. Knepley } 6915b6ebb6e6SMatthew G. Knepley } else { 69169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6917b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6918b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69199371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69209371c9d4SSatish Balay ++cind; 69219371c9d4SSatish Balay continue; 69229371c9d4SSatish Balay } 6923b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6924b6ebb6e6SMatthew G. Knepley } 6925b6ebb6e6SMatthew G. Knepley } else { 6926b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69279371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69289371c9d4SSatish Balay ++cind; 69299371c9d4SSatish Balay continue; 69309371c9d4SSatish Balay } 6931b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6932b6ebb6e6SMatthew G. Knepley } 6933b6ebb6e6SMatthew G. Knepley } 6934b6ebb6e6SMatthew G. Knepley } 6935b6ebb6e6SMatthew G. Knepley } 6936b6ebb6e6SMatthew G. Knepley } 69379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6939b6ebb6e6SMatthew G. Knepley } 69401b406b76SMatthew G. Knepley 69411b406b76SMatthew G. Knepley /*@C 694220f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 69431b406b76SMatthew G. Knepley 69441b406b76SMatthew G. Knepley Not collective 69451b406b76SMatthew G. Knepley 69461b406b76SMatthew G. Knepley Input Parameters: 6947a1cb98faSBarry Smith + dm - The `DM` 694820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 69491b406b76SMatthew G. Knepley . v - The local vector 695020f4b53cSBarry Smith . point - The point in the `DM` 69511b406b76SMatthew G. Knepley . values - The array of values 6952a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6953a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 69541b406b76SMatthew G. Knepley 69551b406b76SMatthew G. Knepley Level: intermediate 69561b406b76SMatthew G. Knepley 69571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 69581b406b76SMatthew G. Knepley @*/ 6959d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6960d71ae5a4SJacob Faibussowitsch { 69611b406b76SMatthew G. Knepley PetscSection clSection; 69621b406b76SMatthew G. Knepley IS clPoints; 69631b406b76SMatthew G. Knepley PetscScalar *array; 69641b406b76SMatthew G. Knepley PetscInt *points = NULL; 696527f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6966c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 69671b406b76SMatthew G. Knepley 69681a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69691b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69709566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69711a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69721a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69751b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69769566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69781b406b76SMatthew G. Knepley } 69791a271a75SMatthew G. Knepley /* Get points */ 698007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6981c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6982c459fbc1SJed Brown PetscInt dof; 69839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6984c459fbc1SJed Brown clsize += dof; 6985c459fbc1SJed Brown } 69869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69871a271a75SMatthew G. Knepley /* Get array */ 69889566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69891a271a75SMatthew G. Knepley /* Get values */ 6990ef90cfe2SMatthew G. Knepley if (numFields > 0) { 699197e99dd9SToby Isaac PetscInt offset = 0, f; 6992552f7358SJed Brown for (f = 0; f < numFields; ++f) { 699397e99dd9SToby Isaac const PetscInt **perms = NULL; 699497e99dd9SToby Isaac const PetscScalar **flips = NULL; 699597e99dd9SToby Isaac 69969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6997552f7358SJed Brown switch (mode) { 6998552f7358SJed Brown case INSERT_VALUES: 699997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70033ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 70049371c9d4SSatish Balay } 70059371c9d4SSatish Balay break; 7006552f7358SJed Brown case INSERT_ALL_VALUES: 700797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70113ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 70129371c9d4SSatish Balay } 70139371c9d4SSatish Balay break; 7014a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 701597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 701697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70193ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 70209371c9d4SSatish Balay } 70219371c9d4SSatish Balay break; 7022552f7358SJed Brown case ADD_VALUES: 702397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70273ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 70289371c9d4SSatish Balay } 70299371c9d4SSatish Balay break; 7030552f7358SJed Brown case ADD_ALL_VALUES: 703197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70353ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 70369371c9d4SSatish Balay } 70379371c9d4SSatish Balay break; 7038304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 703997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 704097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70433ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 70449371c9d4SSatish Balay } 70459371c9d4SSatish Balay break; 7046d71ae5a4SJacob Faibussowitsch default: 7047d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7048552f7358SJed Brown } 70499566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 70501a271a75SMatthew G. Knepley } 7051552f7358SJed Brown } else { 70521a271a75SMatthew G. Knepley PetscInt dof, off; 705397e99dd9SToby Isaac const PetscInt **perms = NULL; 705497e99dd9SToby Isaac const PetscScalar **flips = NULL; 70551a271a75SMatthew G. Knepley 70569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7057552f7358SJed Brown switch (mode) { 7058552f7358SJed Brown case INSERT_VALUES: 705997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70643ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70659371c9d4SSatish Balay } 70669371c9d4SSatish Balay break; 7067552f7358SJed Brown case INSERT_ALL_VALUES: 706897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 707197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70733ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70749371c9d4SSatish Balay } 70759371c9d4SSatish Balay break; 7076a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 707797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70823ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70839371c9d4SSatish Balay } 70849371c9d4SSatish Balay break; 7085552f7358SJed Brown case ADD_VALUES: 708697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 708797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70913ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70929371c9d4SSatish Balay } 70939371c9d4SSatish Balay break; 7094552f7358SJed Brown case ADD_ALL_VALUES: 709597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 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; 70999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71003ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 71019371c9d4SSatish Balay } 71029371c9d4SSatish Balay break; 7103304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 710497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 710597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 710697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 710797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71093ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 71109371c9d4SSatish Balay } 71119371c9d4SSatish Balay break; 7112d71ae5a4SJacob Faibussowitsch default: 7113d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7114552f7358SJed Brown } 71159566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7116552f7358SJed Brown } 71171a271a75SMatthew G. Knepley /* Cleanup points */ 71189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 71191a271a75SMatthew G. Knepley /* Cleanup array */ 71209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7122552f7358SJed Brown } 7123552f7358SJed Brown 71245f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7125d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7126d71ae5a4SJacob Faibussowitsch { 71275f790a90SMatthew G. Knepley PetscFunctionBegin; 712811cc89d2SBarry Smith *contains = PETSC_TRUE; 71295f790a90SMatthew G. Knepley if (label) { 7130d6177c40SToby Isaac PetscInt fdof; 71315f790a90SMatthew G. Knepley 713211cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 713311cc89d2SBarry Smith if (!*contains) { 71349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71355f790a90SMatthew G. Knepley *offset += fdof; 71363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71375f790a90SMatthew G. Knepley } 71385f790a90SMatthew G. Knepley } 71393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71405f790a90SMatthew G. Knepley } 71415f790a90SMatthew G. Knepley 714297529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7143d71ae5a4SJacob 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) 7144d71ae5a4SJacob Faibussowitsch { 7145e07394fbSMatthew G. Knepley PetscSection clSection; 7146e07394fbSMatthew G. Knepley IS clPoints; 7147e07394fbSMatthew G. Knepley PetscScalar *array; 7148e07394fbSMatthew G. Knepley PetscInt *points = NULL; 714997529cf3SJed Brown const PetscInt *clp; 7150e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 715197e99dd9SToby Isaac PetscInt offset = 0, f; 7152e07394fbSMatthew G. Knepley 7153e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7154e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71559566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7156e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7157e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7159e07394fbSMatthew G. Knepley /* Get points */ 716007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7161e07394fbSMatthew G. Knepley /* Get array */ 71629566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7163e07394fbSMatthew G. Knepley /* Get values */ 7164e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 716597e99dd9SToby Isaac const PetscInt **perms = NULL; 716697e99dd9SToby Isaac const PetscScalar **flips = NULL; 716711cc89d2SBarry Smith PetscBool contains; 716897e99dd9SToby Isaac 7169e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7170e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7171e07394fbSMatthew G. Knepley PetscInt fdof; 71729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7173e07394fbSMatthew G. Knepley offset += fdof; 7174e07394fbSMatthew G. Knepley } 7175e07394fbSMatthew G. Knepley continue; 7176e07394fbSMatthew G. Knepley } 71779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7178e07394fbSMatthew G. Knepley switch (mode) { 7179e07394fbSMatthew G. Knepley case INSERT_VALUES: 718097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 718197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 718297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 718397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 718411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 718511cc89d2SBarry Smith if (!contains) continue; 71869566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71879371c9d4SSatish Balay } 71889371c9d4SSatish Balay break; 7189e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 719097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 719197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 719397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 719411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 719511cc89d2SBarry Smith if (!contains) continue; 71969566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 71979371c9d4SSatish Balay } 71989371c9d4SSatish Balay break; 7199e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 720097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 720197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 720411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 720511cc89d2SBarry Smith if (!contains) continue; 72069566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 72079371c9d4SSatish Balay } 72089371c9d4SSatish Balay break; 7209e07394fbSMatthew G. Knepley case ADD_VALUES: 721097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 721197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 721411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 721511cc89d2SBarry Smith if (!contains) continue; 72169566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 72179371c9d4SSatish Balay } 72189371c9d4SSatish Balay break; 7219e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 722097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 722197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 722411cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 722511cc89d2SBarry Smith if (!contains) continue; 72269566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 72279371c9d4SSatish Balay } 72289371c9d4SSatish Balay break; 7229d71ae5a4SJacob Faibussowitsch default: 7230d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7231e07394fbSMatthew G. Knepley } 72329566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7233e07394fbSMatthew G. Knepley } 7234e07394fbSMatthew G. Knepley /* Cleanup points */ 72359566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7236e07394fbSMatthew G. Knepley /* Cleanup array */ 72379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7239e07394fbSMatthew G. Knepley } 7240e07394fbSMatthew G. Knepley 7241d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7242d71ae5a4SJacob Faibussowitsch { 7243552f7358SJed Brown PetscMPIInt rank; 7244552f7358SJed Brown PetscInt i, j; 7245552f7358SJed Brown 7246552f7358SJed Brown PetscFunctionBegin; 72479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 724863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 724963a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 725063a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7251b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 72523ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7253b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 72549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7255b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7256519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 72579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7258552f7358SJed Brown #else 72599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7260552f7358SJed Brown #endif 7261552f7358SJed Brown } 72629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7263552f7358SJed Brown } 72643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7265552f7358SJed Brown } 7266552f7358SJed Brown 726705586334SMatthew G. Knepley /* 726805586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 726905586334SMatthew G. Knepley 727005586334SMatthew G. Knepley Input Parameters: 727105586334SMatthew G. Knepley + section - The section for this data layout 727236fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 727305586334SMatthew G. Knepley . point - The point contributing dofs with these indices 727405586334SMatthew G. Knepley . off - The global offset of this point 727505586334SMatthew G. Knepley . loff - The local offset of each field 7276a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 727705586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 727805586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 727905586334SMatthew G. Knepley 728005586334SMatthew G. Knepley Output Parameter: 728105586334SMatthew G. Knepley . indices - Indices for dofs on this point 728205586334SMatthew G. Knepley 728305586334SMatthew G. Knepley Level: developer 728405586334SMatthew G. Knepley 728505586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 728605586334SMatthew G. Knepley */ 7287d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7288d71ae5a4SJacob Faibussowitsch { 7289e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7290552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7291552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7292552f7358SJed Brown PetscInt cind = 0, k; 7293552f7358SJed Brown 7294552f7358SJed Brown PetscFunctionBegin; 729508401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 72969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7298552f7358SJed Brown if (!cdof || setBC) { 729905586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 730005586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730205586334SMatthew G. Knepley 730305586334SMatthew G. Knepley indices[ind] = off + k; 7304552f7358SJed Brown } 7305552f7358SJed Brown } else { 73069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 73074acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 730805586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731005586334SMatthew G. Knepley 73114acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 73124acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 731305586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 73144acb8e1eSToby Isaac ++cind; 73154acb8e1eSToby Isaac } else { 731636fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7317552f7358SJed Brown } 7318552f7358SJed Brown } 7319552f7358SJed Brown } 7320e6ccafaeSMatthew G Knepley *loff += dof; 73213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7322552f7358SJed Brown } 7323552f7358SJed Brown 73247e29afd2SMatthew G. Knepley /* 732536fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 73267e29afd2SMatthew G. Knepley 732736fa2b79SJed Brown Input Parameters: 732836fa2b79SJed Brown + section - a section (global or local) 732920f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 733036fa2b79SJed Brown . point - point within section 733136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 733236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 733336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 733436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 733536fa2b79SJed Brown . permsoff - offset 733636fa2b79SJed Brown - indperm - index permutation 733736fa2b79SJed Brown 733836fa2b79SJed Brown Output Parameter: 733936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 734036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 734136fa2b79SJed Brown 734236fa2b79SJed Brown Notes: 734336fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 734436fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 734536fa2b79SJed Brown in the local vector. 734636fa2b79SJed Brown 734736fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 734836fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 734936fa2b79SJed Brown 735036fa2b79SJed Brown Developer Note: 735136fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 735236fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 735336fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 735436fa2b79SJed Brown 735536fa2b79SJed Brown Example: 735636fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 735736fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 735836fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 735936fa2b79SJed 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. 736036fa2b79SJed Brown 736136fa2b79SJed Brown Level: developer 73627e29afd2SMatthew G. Knepley */ 7363d71ae5a4SJacob 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[]) 7364d71ae5a4SJacob Faibussowitsch { 7365552f7358SJed Brown PetscInt numFields, foff, f; 7366552f7358SJed Brown 7367552f7358SJed Brown PetscFunctionBegin; 736808401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7370552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73714acb8e1eSToby Isaac PetscInt fdof, cfdof; 7372552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73734acb8e1eSToby Isaac PetscInt cind = 0, b; 73744acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7375552f7358SJed Brown 73769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7378552f7358SJed Brown if (!cfdof || setBC) { 737905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 738205586334SMatthew G. Knepley 738305586334SMatthew G. Knepley indices[ind] = off + foff + b; 738405586334SMatthew G. Knepley } 7385552f7358SJed Brown } else { 73869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 738705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 739005586334SMatthew G. Knepley 73914acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 739205586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7393552f7358SJed Brown ++cind; 7394552f7358SJed Brown } else { 739536fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7396552f7358SJed Brown } 7397552f7358SJed Brown } 7398552f7358SJed Brown } 739936fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7400552f7358SJed Brown foffs[f] += fdof; 7401552f7358SJed Brown } 74023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7403552f7358SJed Brown } 7404552f7358SJed Brown 74057e29afd2SMatthew G. Knepley /* 74067e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 74077e29afd2SMatthew G. Knepley 74087e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7409645102dcSJed Brown 7410645102dcSJed Brown Notes: 7411645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7412645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 74137e29afd2SMatthew G. Knepley */ 7414d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7415d71ae5a4SJacob Faibussowitsch { 74167e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 74177e29afd2SMatthew G. Knepley 74187e29afd2SMatthew G. Knepley PetscFunctionBegin; 74199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 74207e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 74217e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 74227e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 74237e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 74247e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 74257e29afd2SMatthew G. Knepley 74269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 74289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7429645102dcSJed Brown if (!cfdof) { 743005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 743205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 743305586334SMatthew G. Knepley 743405586334SMatthew G. Knepley indices[ind] = foff + b; 743505586334SMatthew G. Knepley } 74367e29afd2SMatthew G. Knepley } else { 74379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 743805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 744005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744105586334SMatthew G. Knepley 74427e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 744305586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 74447e29afd2SMatthew G. Knepley ++cind; 74457e29afd2SMatthew G. Knepley } else { 744605586334SMatthew G. Knepley indices[ind] = foff + b - cind; 74477e29afd2SMatthew G. Knepley } 74487e29afd2SMatthew G. Knepley } 74497e29afd2SMatthew G. Knepley } 74507e29afd2SMatthew G. Knepley foffs[f] += fdof; 74517e29afd2SMatthew G. Knepley } 74523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74537e29afd2SMatthew G. Knepley } 74547e29afd2SMatthew G. Knepley 7455d71ae5a4SJacob 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) 7456d71ae5a4SJacob Faibussowitsch { 7457d3d1a6afSToby Isaac Mat cMat; 7458d3d1a6afSToby Isaac PetscSection aSec, cSec; 7459d3d1a6afSToby Isaac IS aIS; 7460d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7461d3d1a6afSToby Isaac const PetscInt *anchors; 7462e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7463d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7464d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7465d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7466d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7467d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7468d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7469d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 74706ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7471d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7472d3d1a6afSToby Isaac 7473d3d1a6afSToby Isaac PetscFunctionBegin; 7474d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7475d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 74769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7477d3d1a6afSToby Isaac 74789566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7479d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7480d3d1a6afSToby Isaac if (aSec) { 74819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 74829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 74839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7484d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7485d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7486d3d1a6afSToby Isaac * into the global matrix anyway) */ 7487d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7488d3d1a6afSToby Isaac PetscInt b = points[p]; 74894b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7490d3d1a6afSToby Isaac 74919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7492ad540459SPierre Jolivet if (!bSecDof) continue; 749348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7494d3d1a6afSToby Isaac if (bDof) { 7495d3d1a6afSToby Isaac /* this point is constrained */ 7496d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7497d3d1a6afSToby Isaac PetscInt bOff, q; 7498d3d1a6afSToby Isaac 7499d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7500d3d1a6afSToby Isaac newNumPoints += bDof; 75019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7502d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7503d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7504d3d1a6afSToby Isaac PetscInt aDof; 7505d3d1a6afSToby Isaac 75069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7507d3d1a6afSToby Isaac newNumIndices += aDof; 7508d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7509d3d1a6afSToby Isaac PetscInt fDof; 7510d3d1a6afSToby Isaac 75119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7512d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7513d3d1a6afSToby Isaac } 7514d3d1a6afSToby Isaac } 75159371c9d4SSatish Balay } else { 7516d3d1a6afSToby Isaac /* this point is not constrained */ 7517d3d1a6afSToby Isaac newNumPoints++; 75184b2f2278SToby Isaac newNumIndices += bSecDof; 7519d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7520d3d1a6afSToby Isaac PetscInt fDof; 7521d3d1a6afSToby Isaac 75229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7523d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7524d3d1a6afSToby Isaac } 7525d3d1a6afSToby Isaac } 7526d3d1a6afSToby Isaac } 7527d3d1a6afSToby Isaac } 7528d3d1a6afSToby Isaac if (!anyConstrained) { 752972b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 753072b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 753172b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 753272b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 75339566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7535d3d1a6afSToby Isaac } 7536d3d1a6afSToby Isaac 75376ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 75386ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 75396ecaa68aSToby Isaac 7540f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7541d3d1a6afSToby Isaac 75426ecaa68aSToby Isaac if (!outPoints && !outValues) { 75436ecaa68aSToby Isaac if (offsets) { 7544ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 75456ecaa68aSToby Isaac } 75469566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75486ecaa68aSToby Isaac } 75496ecaa68aSToby Isaac 75501dca8a05SBarry 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); 7551d3d1a6afSToby Isaac 75529566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7553d3d1a6afSToby Isaac 7554d3d1a6afSToby Isaac /* workspaces */ 7555d3d1a6afSToby Isaac if (numFields) { 7556d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 75579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 75589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7559d3d1a6afSToby Isaac } 75609371c9d4SSatish Balay } else { 75619566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 75629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7563d3d1a6afSToby Isaac } 7564d3d1a6afSToby Isaac 7565d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7566d3d1a6afSToby Isaac if (numFields) { 75674b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 75684b2f2278SToby Isaac 7569d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7570d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 75714b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7572d3d1a6afSToby Isaac 75739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75744b2f2278SToby Isaac if (!bSecDof) { 75754b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 75764b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 75774b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 75784b2f2278SToby Isaac } 75794b2f2278SToby Isaac continue; 75804b2f2278SToby Isaac } 758148a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7582d3d1a6afSToby Isaac if (bDof) { 7583d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7584d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7585d3d1a6afSToby Isaac 75869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 75879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7588d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7589d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7590d3d1a6afSToby Isaac PetscInt aFDof; 7591d3d1a6afSToby Isaac 75929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7593d3d1a6afSToby Isaac allFDof += aFDof; 7594d3d1a6afSToby Isaac } 7595d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7596d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7597d3d1a6afSToby Isaac } 75989371c9d4SSatish Balay } else { 7599d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7600d3d1a6afSToby Isaac PetscInt fDof; 7601d3d1a6afSToby Isaac 76029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7603d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7604d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7605d3d1a6afSToby Isaac } 7606d3d1a6afSToby Isaac } 7607d3d1a6afSToby Isaac } 76084b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 76094b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 76104b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7611d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7612d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7613d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7614d3d1a6afSToby Isaac } 761519f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 761619f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 76179566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7618d3d1a6afSToby Isaac } 76199371c9d4SSatish Balay } else { 7620d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7621d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 76224b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7623d3d1a6afSToby Isaac 76249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 76254b2f2278SToby Isaac if (!bSecDof) { 76264b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 76274b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 76284b2f2278SToby Isaac continue; 76294b2f2278SToby Isaac } 763048a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7631d3d1a6afSToby Isaac if (bDof) { 76324b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7633d3d1a6afSToby Isaac 76349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7635d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7636d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7637d3d1a6afSToby Isaac 76389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7639d3d1a6afSToby Isaac allDof += aDof; 7640d3d1a6afSToby Isaac } 7641d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 76424b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 76439371c9d4SSatish Balay } else { 76444b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7645d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7646d3d1a6afSToby Isaac } 7647d3d1a6afSToby Isaac } 7648d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7649d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7650d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7651d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7652d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7653d3d1a6afSToby Isaac } 76549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7655d3d1a6afSToby Isaac } 7656d3d1a6afSToby Isaac 76576ecaa68aSToby Isaac /* output arrays */ 76589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 76596ecaa68aSToby Isaac 7660d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 76619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 76629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 76639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 76649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7665d3d1a6afSToby Isaac if (numFields) { 7666d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7667d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7668d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 76694b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7670d3d1a6afSToby Isaac 76719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7672ad540459SPierre Jolivet if (!bSecDof) continue; 767348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7674d3d1a6afSToby Isaac if (bDof) { 7675d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7676d3d1a6afSToby Isaac 7677d3d1a6afSToby Isaac fStart[0] = 0; 7678d3d1a6afSToby Isaac fEnd[0] = 0; 7679d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7680d3d1a6afSToby Isaac PetscInt fDof; 7681d3d1a6afSToby Isaac 76829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7683d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7684d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7685d3d1a6afSToby Isaac } 76869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76879566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7688d3d1a6afSToby Isaac 7689d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7690d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7691d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7692d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7693d3d1a6afSToby Isaac 7694d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7695d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7696d3d1a6afSToby Isaac } 76979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7698d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7699d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7700d3d1a6afSToby Isaac 7701d3d1a6afSToby 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 */ 7702d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7703d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77059566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7706d3d1a6afSToby Isaac } 7707d3d1a6afSToby Isaac newP += bDof; 7708d3d1a6afSToby Isaac 77096ecaa68aSToby Isaac if (outValues) { 7710d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 771148a46eb9SPierre 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])); 7712d3d1a6afSToby Isaac } 77139371c9d4SSatish Balay } else { 7714d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7715d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7716d3d1a6afSToby Isaac newP++; 7717d3d1a6afSToby Isaac } 7718d3d1a6afSToby Isaac } 7719d3d1a6afSToby Isaac } else { 7720d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7721d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7722d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 77234b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7724d3d1a6afSToby Isaac 77259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7726ad540459SPierre Jolivet if (!bSecDof) continue; 772748a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7728d3d1a6afSToby Isaac if (bDof) { 7729d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7730d3d1a6afSToby Isaac 77319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 77329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7733d3d1a6afSToby Isaac 77349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7735d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7736d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7737d3d1a6afSToby Isaac 7738d3d1a6afSToby 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 */ 7739d3d1a6afSToby Isaac 7740d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7741d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77439566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7744d3d1a6afSToby Isaac } 7745d3d1a6afSToby Isaac newP += bDof; 7746d3d1a6afSToby Isaac 7747d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 774848a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 77499371c9d4SSatish Balay } else { 7750d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7751d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7752d3d1a6afSToby Isaac newP++; 7753d3d1a6afSToby Isaac } 7754d3d1a6afSToby Isaac } 7755d3d1a6afSToby Isaac } 7756d3d1a6afSToby Isaac 77576ecaa68aSToby Isaac if (outValues) { 77589566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 77599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7760d3d1a6afSToby Isaac /* multiply constraints on the right */ 7761d3d1a6afSToby Isaac if (numFields) { 7762d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7763d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7764d3d1a6afSToby Isaac 7765d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7766d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7767d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7768d3d1a6afSToby Isaac PetscInt c, r, k; 7769d3d1a6afSToby Isaac PetscInt dof; 7770d3d1a6afSToby Isaac 77719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7772ad540459SPierre Jolivet if (!dof) continue; 7773d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7774d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7775d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7776d3d1a6afSToby Isaac 7777d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7778d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7779ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7780d3d1a6afSToby Isaac } 7781d3d1a6afSToby Isaac } 77829371c9d4SSatish Balay } else { 7783d3d1a6afSToby Isaac /* copy this column as is */ 7784d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7785ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7786d3d1a6afSToby Isaac } 7787d3d1a6afSToby Isaac } 7788d3d1a6afSToby Isaac oldOff += dof; 7789d3d1a6afSToby Isaac } 7790d3d1a6afSToby Isaac } 77919371c9d4SSatish Balay } else { 7792d3d1a6afSToby Isaac PetscInt oldOff = 0; 7793d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7794d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7795d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7796d3d1a6afSToby Isaac PetscInt c, r, k; 7797d3d1a6afSToby Isaac PetscInt dof; 7798d3d1a6afSToby Isaac 77999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7800ad540459SPierre Jolivet if (!dof) continue; 7801d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7802d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7803d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7804d3d1a6afSToby Isaac 7805d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7806d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7807ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7808d3d1a6afSToby Isaac } 7809d3d1a6afSToby Isaac } 78109371c9d4SSatish Balay } else { 7811d3d1a6afSToby Isaac /* copy this column as is */ 7812d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7813ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7814d3d1a6afSToby Isaac } 7815d3d1a6afSToby Isaac } 7816d3d1a6afSToby Isaac oldOff += dof; 7817d3d1a6afSToby Isaac } 7818d3d1a6afSToby Isaac } 7819d3d1a6afSToby Isaac 78206ecaa68aSToby Isaac if (multiplyLeft) { 78219566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 78229566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7823d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7824d3d1a6afSToby Isaac if (numFields) { 7825d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7826d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7827d3d1a6afSToby Isaac 7828d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7829d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7830d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7831d3d1a6afSToby Isaac PetscInt c, r, k; 7832d3d1a6afSToby Isaac PetscInt dof; 7833d3d1a6afSToby Isaac 78349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7835d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7836d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7837d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7838d3d1a6afSToby Isaac 7839d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7840d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7841ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7842d3d1a6afSToby Isaac } 7843d3d1a6afSToby Isaac } 78449371c9d4SSatish Balay } else { 7845d3d1a6afSToby Isaac /* copy this row as is */ 7846d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7847ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7848d3d1a6afSToby Isaac } 7849d3d1a6afSToby Isaac } 7850d3d1a6afSToby Isaac oldOff += dof; 7851d3d1a6afSToby Isaac } 7852d3d1a6afSToby Isaac } 78539371c9d4SSatish Balay } else { 7854d3d1a6afSToby Isaac PetscInt oldOff = 0; 7855d3d1a6afSToby Isaac 7856d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7857d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7858d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7859d3d1a6afSToby Isaac PetscInt c, r, k; 7860d3d1a6afSToby Isaac PetscInt dof; 7861d3d1a6afSToby Isaac 78629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7863d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7864d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7865d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7866d3d1a6afSToby Isaac 7867d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7868d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7869ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7870d3d1a6afSToby Isaac } 7871d3d1a6afSToby Isaac } 78729371c9d4SSatish Balay } else { 7873d3d1a6afSToby Isaac /* copy this row as is */ 78749fc93327SToby Isaac for (r = 0; r < dof; r++) { 7875ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7876d3d1a6afSToby Isaac } 7877d3d1a6afSToby Isaac } 7878d3d1a6afSToby Isaac oldOff += dof; 7879d3d1a6afSToby Isaac } 7880d3d1a6afSToby Isaac } 7881d3d1a6afSToby Isaac 78829566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 78839371c9d4SSatish Balay } else { 78846ecaa68aSToby Isaac newValues = tmpValues; 78856ecaa68aSToby Isaac } 78866ecaa68aSToby Isaac } 78876ecaa68aSToby Isaac 7888d3d1a6afSToby Isaac /* clean up */ 78899566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 78909566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 78916ecaa68aSToby Isaac 7892d3d1a6afSToby Isaac if (numFields) { 7893d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 78949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 78959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 78969566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7897d3d1a6afSToby Isaac } 78989371c9d4SSatish Balay } else { 78999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 79009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 79019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7902d3d1a6afSToby Isaac } 79039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7904d3d1a6afSToby Isaac 7905d3d1a6afSToby Isaac /* output */ 79066ecaa68aSToby Isaac if (outPoints) { 7907d3d1a6afSToby Isaac *outPoints = newPoints; 79089371c9d4SSatish Balay } else { 79099566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 79106ecaa68aSToby Isaac } 7911ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7912ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 79133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7914d3d1a6afSToby Isaac } 7915d3d1a6afSToby Isaac 79164a1e0b3eSMatthew G. Knepley /*@C 791771f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 79187cd05799SMatthew G. Knepley 79197cd05799SMatthew G. Knepley Not collective 79207cd05799SMatthew G. Knepley 79217cd05799SMatthew G. Knepley Input Parameters: 7922a1cb98faSBarry Smith + dm - The `DM` 7923a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7924a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 792571f0bbf9SMatthew G. Knepley . point - The point defining the closure 792671f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 79277cd05799SMatthew G. Knepley 792871f0bbf9SMatthew G. Knepley Output Parameters: 792971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 793071f0bbf9SMatthew G. Knepley . indices - The dof indices 793120f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 793220f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 79337cd05799SMatthew G. Knepley 7934a1cb98faSBarry Smith Level: advanced 793536fa2b79SJed Brown 7936a1cb98faSBarry Smith Notes: 7937a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7938a1cb98faSBarry Smith 793920f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 794020f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 794136fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 794220f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 794336fa2b79SJed Brown indices (with the above semantics) are implied. 79447cd05799SMatthew G. Knepley 79451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7946a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 79474a1e0b3eSMatthew G. Knepley @*/ 7948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7949d71ae5a4SJacob Faibussowitsch { 795071f0bbf9SMatthew G. Knepley /* Closure ordering */ 79517773e69fSMatthew G. Knepley PetscSection clSection; 79527773e69fSMatthew G. Knepley IS clPoints; 795371f0bbf9SMatthew G. Knepley const PetscInt *clp; 795471f0bbf9SMatthew G. Knepley PetscInt *points; 795571f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 795671f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 79574acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 795871f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 795971f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 796071f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 796171f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 796271f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 796371f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 796471f0bbf9SMatthew G. Knepley 796571f0bbf9SMatthew G. Knepley PetscInt *idx; 796671f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 796771f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 79687773e69fSMatthew G. Knepley 796971f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 79707773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79717773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 797236fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 79734f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 79744f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 79754f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 79764f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 79779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 797863a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 79799566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 798071f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 798107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7982c459fbc1SJed Brown if (useClPerm) { 7983c459fbc1SJed Brown PetscInt depth, clsize; 79849566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7985c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7986c459fbc1SJed Brown PetscInt dof; 79879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7988c459fbc1SJed Brown clsize += dof; 7989c459fbc1SJed Brown } 79909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7991c459fbc1SJed Brown } 799271f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 799371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 79947773e69fSMatthew G. Knepley PetscInt dof, fdof; 79957773e69fSMatthew G. Knepley 79969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 79977773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 79989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 79997773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 80007773e69fSMatthew G. Knepley } 800171f0bbf9SMatthew G. Knepley Ni += dof; 80027773e69fSMatthew G. Knepley } 80037773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 80041dca8a05SBarry 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); 800571f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 800671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80079566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80089566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 800971f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 801071f0bbf9SMatthew G. Knepley if (values && flips[f]) { 801171f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 80126ecaa68aSToby Isaac 801371f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 801471f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 801571f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 801671f0bbf9SMatthew G. Knepley 80179566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 80189566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 801971f0bbf9SMatthew G. Knepley if (flip) { 802071f0bbf9SMatthew G. Knepley PetscInt i, j, k; 802171f0bbf9SMatthew G. Knepley 802271f0bbf9SMatthew G. Knepley if (!valCopy) { 80239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 802471f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 802571f0bbf9SMatthew G. Knepley *values = valCopy; 802671f0bbf9SMatthew G. Knepley } 802771f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 802871f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 802971f0bbf9SMatthew G. Knepley 803071f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 803171f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 803271f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 80336ecaa68aSToby Isaac } 80346ecaa68aSToby Isaac } 803571f0bbf9SMatthew G. Knepley } 803671f0bbf9SMatthew G. Knepley foffset += fdof; 803771f0bbf9SMatthew G. Knepley } 803871f0bbf9SMatthew G. Knepley } 803971f0bbf9SMatthew G. Knepley } 804071f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 80419566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 804271f0bbf9SMatthew G. Knepley if (NclC) { 80439566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 804471f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80459566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80469566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 804771f0bbf9SMatthew G. Knepley } 804871f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80499566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 80509566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 805171f0bbf9SMatthew G. Knepley } 80529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 805371f0bbf9SMatthew G. Knepley Ncl = NclC; 805471f0bbf9SMatthew G. Knepley Ni = NiC; 805571f0bbf9SMatthew G. Knepley points = pointsC; 805671f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 805771f0bbf9SMatthew G. Knepley } 805871f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 80599566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 806071f0bbf9SMatthew G. Knepley if (Nf) { 806171f0bbf9SMatthew G. Knepley PetscInt idxOff; 806271f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 806371f0bbf9SMatthew G. Knepley 80649371c9d4SSatish Balay if (outOffsets) { 80659371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 80669371c9d4SSatish Balay } 80679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 806871f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 806971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 807071f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 807171f0bbf9SMatthew G. Knepley 80729566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 80737773e69fSMatthew G. Knepley } 80747773e69fSMatthew G. Knepley } else { 807571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 807671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 807771f0bbf9SMatthew G. Knepley 80789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 807971f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 808071f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 808171f0bbf9SMatthew G. Knepley * global section. */ 80829566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 808371f0bbf9SMatthew G. Knepley } 808471f0bbf9SMatthew G. Knepley } 808571f0bbf9SMatthew G. Knepley } else { 808671f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 808771f0bbf9SMatthew G. Knepley 808871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 808971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 80904acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 80914acb8e1eSToby Isaac 80929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 809371f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 809471f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 80959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 80967773e69fSMatthew G. Knepley } 80977773e69fSMatthew G. Knepley } 809871f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 809971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 81009566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 81019566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 81024acb8e1eSToby Isaac } 810371f0bbf9SMatthew G. Knepley if (NclC) { 81049566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 81057773e69fSMatthew G. Knepley } else { 81069566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 81077773e69fSMatthew G. Knepley } 810871f0bbf9SMatthew G. Knepley 810971f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 811071f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 81113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81127773e69fSMatthew G. Knepley } 81137773e69fSMatthew G. Knepley 81147cd05799SMatthew G. Knepley /*@C 811571f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 81167cd05799SMatthew G. Knepley 81177cd05799SMatthew G. Knepley Not collective 81187cd05799SMatthew G. Knepley 81197cd05799SMatthew G. Knepley Input Parameters: 8120a1cb98faSBarry Smith + dm - The `DM` 8121a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8122a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 812371f0bbf9SMatthew G. Knepley . point - The point defining the closure 812471f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 812571f0bbf9SMatthew G. Knepley 812671f0bbf9SMatthew G. Knepley Output Parameters: 812771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 812871f0bbf9SMatthew G. Knepley . indices - The dof indices 812920f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 813020f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 813171f0bbf9SMatthew G. Knepley 8132a1cb98faSBarry Smith Level: advanced 813371f0bbf9SMatthew G. Knepley 8134a1cb98faSBarry Smith Notes: 8135a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8136a1cb98faSBarry Smith 8137a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 813871f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 813971f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 814071f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 814171f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 81427cd05799SMatthew G. Knepley 81431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 81447cd05799SMatthew G. Knepley @*/ 8145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8146d71ae5a4SJacob Faibussowitsch { 81477773e69fSMatthew G. Knepley PetscFunctionBegin; 81487773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81494f572ea9SToby Isaac PetscAssertPointer(indices, 7); 81509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 81513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81527773e69fSMatthew G. Knepley } 81537773e69fSMatthew G. Knepley 8154e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8155d71ae5a4SJacob Faibussowitsch { 8156552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8157552f7358SJed Brown PetscInt *indices; 815871f0bbf9SMatthew G. Knepley PetscInt numIndices; 815971f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8160552f7358SJed Brown PetscErrorCode ierr; 8161552f7358SJed Brown 8162552f7358SJed Brown PetscFunctionBegin; 8163552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81649566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 81653dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 81669566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 81673dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8168e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8169552f7358SJed Brown 8170e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81710d644c17SKarl Rupp 81729566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8173d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81744a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8175552f7358SJed Brown if (ierr) { 8176552f7358SJed Brown PetscMPIInt rank; 8177552f7358SJed Brown 81789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81799566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81809566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81829566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8183c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8184552f7358SJed Brown } 81854a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81864a1e0b3eSMatthew G. Knepley PetscInt i; 81879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 818863a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81904a1e0b3eSMatthew G. Knepley } 819171f0bbf9SMatthew G. Knepley 81929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81939566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 81943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81954acb8e1eSToby Isaac } 819671f0bbf9SMatthew G. Knepley 81974a1e0b3eSMatthew G. Knepley /*@C 8198e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8199e8e188d2SZach Atkins 8200e8e188d2SZach Atkins Not collective 8201e8e188d2SZach Atkins 8202e8e188d2SZach Atkins Input Parameters: 8203e8e188d2SZach Atkins + dm - The `DM` 8204e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8205e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8206e8e188d2SZach Atkins . A - The matrix 8207e8e188d2SZach Atkins . point - The point in the `DM` 8208e8e188d2SZach Atkins . values - The array of values 8209e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8210e8e188d2SZach Atkins 8211e8e188d2SZach Atkins Level: intermediate 8212e8e188d2SZach Atkins 8213e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8214e8e188d2SZach Atkins @*/ 8215e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8216e8e188d2SZach Atkins { 8217e8e188d2SZach Atkins PetscFunctionBegin; 8218e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8219e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8220e8e188d2SZach Atkins } 8221e8e188d2SZach Atkins 8222e8e188d2SZach Atkins /*@C 822360225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 82244a1e0b3eSMatthew G. Knepley 82254a1e0b3eSMatthew G. Knepley Not collective 82264a1e0b3eSMatthew G. Knepley 82274a1e0b3eSMatthew G. Knepley Input Parameters: 8228a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 822920f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8230e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 823120f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8232a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 823320f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8234e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 823520f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 82364a1e0b3eSMatthew G. Knepley . A - The matrix 8237a1cb98faSBarry Smith . point - The point in the `DM` 82384a1e0b3eSMatthew G. Knepley . values - The array of values 8239a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 82404a1e0b3eSMatthew G. Knepley 82414a1e0b3eSMatthew G. Knepley Level: intermediate 82424a1e0b3eSMatthew G. Knepley 82431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 82444a1e0b3eSMatthew G. Knepley @*/ 8245e8e188d2SZach 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) 8246d71ae5a4SJacob Faibussowitsch { 824771f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 824871f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 824971f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 825071f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 825171f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 825271f0bbf9SMatthew G. Knepley 825371f0bbf9SMatthew G. Knepley PetscFunctionBegin; 825471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 82559566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 825671f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 82579566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 825871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8259e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 82609566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8261e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 82629566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8263e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8264e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 826571f0bbf9SMatthew G. Knepley 8266e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8267e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 826871f0bbf9SMatthew G. Knepley 82699566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 8270d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 82714a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 827271f0bbf9SMatthew G. Knepley if (ierr) { 827371f0bbf9SMatthew G. Knepley PetscMPIInt rank; 827471f0bbf9SMatthew G. Knepley 82759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82769566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82779566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 82799566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 82809566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 8281d3d1a6afSToby Isaac } 828271f0bbf9SMatthew G. Knepley 8283e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8284e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 82859566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 82863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8287552f7358SJed Brown } 8288552f7358SJed Brown 8289d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8290d71ae5a4SJacob Faibussowitsch { 8291de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8292de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8293de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8294de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 829517c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8296de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8297412e9a14SMatthew G. Knepley DMPolytopeType ct; 82984ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8299de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8300de41b84cSMatthew G. Knepley 8301de41b84cSMatthew G. Knepley PetscFunctionBegin; 8302de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8303de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83049566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8305de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 83069566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8307de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 83089566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8309de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 83109566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8311de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8312de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 83139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 831463a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 83159566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 83169566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8317de41b84cSMatthew G. Knepley /* Column indices */ 83189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83194ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8320de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8321de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 83229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8323de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8324de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8325de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8326de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8327de41b84cSMatthew G. Knepley ++q; 8328de41b84cSMatthew G. Knepley } 8329de41b84cSMatthew G. Knepley } 8330de41b84cSMatthew G. Knepley numCPoints = q; 8331de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8332de41b84cSMatthew G. Knepley PetscInt fdof; 8333de41b84cSMatthew G. Knepley 83349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 83354ca5e9f5SMatthew G. Knepley if (!dof) continue; 8336de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8338de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8339de41b84cSMatthew G. Knepley } 8340de41b84cSMatthew G. Knepley numCIndices += dof; 8341de41b84cSMatthew G. Knepley } 8342de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8343de41b84cSMatthew G. Knepley /* Row indices */ 83449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8345412e9a14SMatthew G. Knepley { 8346012bc364SMatthew G. Knepley DMPlexTransform tr; 8347012bc364SMatthew G. Knepley DMPolytopeType *rct; 8348012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8349012bc364SMatthew G. Knepley 83509566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 83519566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 83529566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8353012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 83549566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8355412e9a14SMatthew G. Knepley } 83569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8357de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8358de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 83599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8360de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 83619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8362de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8363de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 83649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 83654ca5e9f5SMatthew G. Knepley if (!dof) continue; 83669371c9d4SSatish Balay for (s = 0; s < q; ++s) 83679371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 83684ca5e9f5SMatthew G. Knepley if (s < q) continue; 8369de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8370de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8371de41b84cSMatthew G. Knepley ++q; 8372de41b84cSMatthew G. Knepley } 8373de41b84cSMatthew G. Knepley } 83749566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8375de41b84cSMatthew G. Knepley } 8376de41b84cSMatthew G. Knepley numFPoints = q; 8377de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8378de41b84cSMatthew G. Knepley PetscInt fdof; 8379de41b84cSMatthew G. Knepley 83809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83814ca5e9f5SMatthew G. Knepley if (!dof) continue; 8382de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8384de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8385de41b84cSMatthew G. Knepley } 8386de41b84cSMatthew G. Knepley numFIndices += dof; 8387de41b84cSMatthew G. Knepley } 8388de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8389de41b84cSMatthew G. Knepley 83901dca8a05SBarry 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); 83911dca8a05SBarry 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); 83929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83939566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8394de41b84cSMatthew G. Knepley if (numFields) { 83954acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 83964acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 83974acb8e1eSToby Isaac 83984acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8401de41b84cSMatthew G. Knepley } 84024acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84049566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84054acb8e1eSToby Isaac } 84064acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84089566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84094acb8e1eSToby Isaac } 84104acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84119566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84129566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8413de41b84cSMatthew G. Knepley } 8414de41b84cSMatthew G. Knepley } else { 84154acb8e1eSToby Isaac const PetscInt **permsF = NULL; 84164acb8e1eSToby Isaac const PetscInt **permsC = NULL; 84174acb8e1eSToby Isaac 84189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84204acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 84214acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 84224acb8e1eSToby Isaac 84239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84249566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8425de41b84cSMatthew G. Knepley } 84264acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 84274acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 84284acb8e1eSToby Isaac 84299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84309566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8431de41b84cSMatthew G. Knepley } 84329566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84339566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8434de41b84cSMatthew G. Knepley } 84359566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84364acb8e1eSToby Isaac /* TODO: flips */ 8437d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8438de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8439de41b84cSMatthew G. Knepley if (ierr) { 8440de41b84cSMatthew G. Knepley PetscMPIInt rank; 8441de41b84cSMatthew G. Knepley 84429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 84439566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 84449566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84459566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84469566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8447de41b84cSMatthew G. Knepley } 84489566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 84499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84509566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 84523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8453de41b84cSMatthew G. Knepley } 8454de41b84cSMatthew G. Knepley 8455d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8456d71ae5a4SJacob Faibussowitsch { 84577c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 84587c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 84597c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 846017c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8461412e9a14SMatthew G. Knepley DMPolytopeType ct; 84627c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 84637c927364SMatthew G. Knepley 84647c927364SMatthew G. Knepley PetscFunctionBegin; 84657c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 84667c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 84679566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 84687c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84699566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84707c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84719566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84727c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84739566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84747c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 847663a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84779566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 84789566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 84797c927364SMatthew G. Knepley /* Column indices */ 84809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84817c927364SMatthew G. Knepley maxFPoints = numCPoints; 84827c927364SMatthew G. Knepley /* Compress out points not in the section */ 84837c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84857c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84867c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84877c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84887c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84897c927364SMatthew G. Knepley ++q; 84907c927364SMatthew G. Knepley } 84917c927364SMatthew G. Knepley } 84927c927364SMatthew G. Knepley numCPoints = q; 84937c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84947c927364SMatthew G. Knepley PetscInt fdof; 84957c927364SMatthew G. Knepley 84969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 84977c927364SMatthew G. Knepley if (!dof) continue; 84987c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 85007c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 85017c927364SMatthew G. Knepley } 85027c927364SMatthew G. Knepley numCIndices += dof; 85037c927364SMatthew G. Knepley } 85047c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 85057c927364SMatthew G. Knepley /* Row indices */ 85069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8507412e9a14SMatthew G. Knepley { 8508012bc364SMatthew G. Knepley DMPlexTransform tr; 8509012bc364SMatthew G. Knepley DMPolytopeType *rct; 8510012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8511012bc364SMatthew G. Knepley 85129566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 85139566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 85149566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8515012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 85169566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8517412e9a14SMatthew G. Knepley } 85189566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 85197c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 85207c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 85219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 85227c927364SMatthew G. Knepley /* Compress out points not in the section */ 85239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 85247c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 85257c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 85269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 85277c927364SMatthew G. Knepley if (!dof) continue; 85289371c9d4SSatish Balay for (s = 0; s < q; ++s) 85299371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 85307c927364SMatthew G. Knepley if (s < q) continue; 85317c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 85327c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 85337c927364SMatthew G. Knepley ++q; 85347c927364SMatthew G. Knepley } 85357c927364SMatthew G. Knepley } 85369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 85377c927364SMatthew G. Knepley } 85387c927364SMatthew G. Knepley numFPoints = q; 85397c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 85407c927364SMatthew G. Knepley PetscInt fdof; 85417c927364SMatthew G. Knepley 85429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 85437c927364SMatthew G. Knepley if (!dof) continue; 85447c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 85467c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 85477c927364SMatthew G. Knepley } 85487c927364SMatthew G. Knepley numFIndices += dof; 85497c927364SMatthew G. Knepley } 85507c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 85517c927364SMatthew G. Knepley 85521dca8a05SBarry 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); 85531dca8a05SBarry 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); 85547c927364SMatthew G. Knepley if (numFields) { 85554acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 85564acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 85574acb8e1eSToby Isaac 85584acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85617c927364SMatthew G. Knepley } 85624acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 85639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85649566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 85654acb8e1eSToby Isaac } 85664acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 85679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 85694acb8e1eSToby Isaac } 85704acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85719566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85729566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85737c927364SMatthew G. Knepley } 85747c927364SMatthew G. Knepley } else { 85754acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85764acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85774acb8e1eSToby Isaac 85789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85804acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85814acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85824acb8e1eSToby Isaac 85839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85849566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85857c927364SMatthew G. Knepley } 85864acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85874acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85884acb8e1eSToby Isaac 85899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85909566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85917c927364SMatthew G. Knepley } 85929566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85939566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85947c927364SMatthew G. Knepley } 85959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 85969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85987c927364SMatthew G. Knepley } 85997c927364SMatthew G. Knepley 86007cd05799SMatthew G. Knepley /*@C 86017cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 86027cd05799SMatthew G. Knepley 86037cd05799SMatthew G. Knepley Input Parameter: 8604a1cb98faSBarry Smith . dm - The `DMPLEX` object 86057cd05799SMatthew G. Knepley 86067cd05799SMatthew G. Knepley Output Parameter: 86077cd05799SMatthew G. Knepley . cellHeight - The height of a cell 86087cd05799SMatthew G. Knepley 86097cd05799SMatthew G. Knepley Level: developer 86107cd05799SMatthew G. Knepley 86111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 86127cd05799SMatthew G. Knepley @*/ 8613d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8614d71ae5a4SJacob Faibussowitsch { 8615552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8616552f7358SJed Brown 8617552f7358SJed Brown PetscFunctionBegin; 8618552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86194f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8620552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 86213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8622552f7358SJed Brown } 8623552f7358SJed Brown 86247cd05799SMatthew G. Knepley /*@C 86257cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 86267cd05799SMatthew G. Knepley 86277cd05799SMatthew G. Knepley Input Parameters: 8628a1cb98faSBarry Smith + dm - The `DMPLEX` object 86297cd05799SMatthew G. Knepley - cellHeight - The height of a cell 86307cd05799SMatthew G. Knepley 86317cd05799SMatthew G. Knepley Level: developer 86327cd05799SMatthew G. Knepley 86331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 86347cd05799SMatthew G. Knepley @*/ 8635d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8636d71ae5a4SJacob Faibussowitsch { 8637552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8638552f7358SJed Brown 8639552f7358SJed Brown PetscFunctionBegin; 8640552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8641552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 86423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8643552f7358SJed Brown } 8644552f7358SJed Brown 8645e6139122SMatthew G. Knepley /*@ 86462827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8647e6139122SMatthew G. Knepley 86482827ebadSStefano Zampini Input Parameters: 86492827ebadSStefano Zampini + dm - The `DMPLEX` object 86502827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8651e6139122SMatthew G. Knepley 8652e6139122SMatthew G. Knepley Output Parameters: 86532827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 86542827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8655e6139122SMatthew G. Knepley 86562a9f31c0SMatthew G. Knepley Level: advanced 8657e6139122SMatthew G. Knepley 86582827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8659e6139122SMatthew G. Knepley @*/ 86602827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8661d71ae5a4SJacob Faibussowitsch { 86622827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 86632827ebadSStefano Zampini DMLabel label; 86642827ebadSStefano Zampini PetscInt pStart, pEnd; 8665e6139122SMatthew G. Knepley 8666e6139122SMatthew G. Knepley PetscFunctionBegin; 8667e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86682827ebadSStefano Zampini if (start) { 86694f572ea9SToby Isaac PetscAssertPointer(start, 3); 86702827ebadSStefano Zampini *start = 0; 86712827ebadSStefano Zampini } 86722827ebadSStefano Zampini if (end) { 86734f572ea9SToby Isaac PetscAssertPointer(end, 4); 86742827ebadSStefano Zampini *end = 0; 86752827ebadSStefano Zampini } 86762827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86772827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86782827ebadSStefano Zampini if (mesh->tr) { 86792827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86802827ebadSStefano Zampini } else { 86812827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86822827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86832827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86842827ebadSStefano Zampini } 86853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8686e6139122SMatthew G. Knepley } 8687e6139122SMatthew G. Knepley 8688d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8689d71ae5a4SJacob Faibussowitsch { 8690552f7358SJed Brown PetscSection section, globalSection; 8691552f7358SJed Brown PetscInt *numbers, p; 8692552f7358SJed Brown 8693552f7358SJed Brown PetscFunctionBegin; 8694d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 86959566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 86969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 869748a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 86989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 86999566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 87009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8701552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 87029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8703ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8704ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8705552f7358SJed Brown } 87069566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8707ef48cebcSMatthew G. Knepley if (globalSize) { 8708ef48cebcSMatthew G. Knepley PetscLayout layout; 87099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 87109566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 87119566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8712ef48cebcSMatthew G. Knepley } 87139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 87149566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 87153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8716552f7358SJed Brown } 8717552f7358SJed Brown 8718d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8719d71ae5a4SJacob Faibussowitsch { 8720412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8721552f7358SJed Brown 8722552f7358SJed Brown PetscFunctionBegin; 87239566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87249566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 87259566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 87269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 87273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8728552f7358SJed Brown } 872981ed3555SMatthew G. Knepley 87308dab3259SMatthew G. Knepley /*@ 87317cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 87327cd05799SMatthew G. Knepley 87337cd05799SMatthew G. Knepley Input Parameter: 8734a1cb98faSBarry Smith . dm - The `DMPLEX` object 87357cd05799SMatthew G. Knepley 87367cd05799SMatthew G. Knepley Output Parameter: 87377cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 87387cd05799SMatthew G. Knepley 87397cd05799SMatthew G. Knepley Level: developer 87407cd05799SMatthew G. Knepley 87411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 87427cd05799SMatthew G. Knepley @*/ 8743d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8744d71ae5a4SJacob Faibussowitsch { 874581ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 874681ed3555SMatthew G. Knepley 874781ed3555SMatthew G. Knepley PetscFunctionBegin; 874881ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87499566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8750552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 87513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8752552f7358SJed Brown } 8753552f7358SJed Brown 8754d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8755d71ae5a4SJacob Faibussowitsch { 8756412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 875781ed3555SMatthew G. Knepley 875881ed3555SMatthew G. Knepley PetscFunctionBegin; 875981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 87619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 87623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 876381ed3555SMatthew G. Knepley } 876481ed3555SMatthew G. Knepley 87658dab3259SMatthew G. Knepley /*@ 87666aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 87677cd05799SMatthew G. Knepley 87687cd05799SMatthew G. Knepley Input Parameter: 8769a1cb98faSBarry Smith . dm - The `DMPLEX` object 87707cd05799SMatthew G. Knepley 87717cd05799SMatthew G. Knepley Output Parameter: 87727cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87737cd05799SMatthew G. Knepley 87747cd05799SMatthew G. Knepley Level: developer 87757cd05799SMatthew G. Knepley 87761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87777cd05799SMatthew G. Knepley @*/ 8778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8779d71ae5a4SJacob Faibussowitsch { 8780552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8781552f7358SJed Brown 8782552f7358SJed Brown PetscFunctionBegin; 8783552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87849566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8785552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8787552f7358SJed Brown } 8788552f7358SJed Brown 87898dab3259SMatthew G. Knepley /*@ 8790966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8791966484cfSJed Brown 879220f4b53cSBarry Smith Collective 87937cd05799SMatthew G. Knepley 87947cd05799SMatthew G. Knepley Input Parameter: 8795a1cb98faSBarry Smith . dm - The `DMPLEX` object 87967cd05799SMatthew G. Knepley 87977cd05799SMatthew G. Knepley Output Parameter: 87987cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 87997cd05799SMatthew G. Knepley 8800a1cb98faSBarry Smith Level: developer 8801966484cfSJed Brown 8802a1cb98faSBarry Smith Notes: 8803a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8804966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8805966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8806966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8807966484cfSJed Brown 8808966484cfSJed Brown The partitioned mesh is 8809966484cfSJed Brown ``` 8810966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8811966484cfSJed Brown ``` 8812966484cfSJed Brown and its global numbering is 8813966484cfSJed Brown ``` 8814966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8815966484cfSJed Brown ``` 8816966484cfSJed Brown Then the global numbering is provided as 8817966484cfSJed Brown ``` 8818966484cfSJed Brown [0] Number of indices in set 5 8819966484cfSJed Brown [0] 0 0 8820966484cfSJed Brown [0] 1 1 8821966484cfSJed Brown [0] 2 3 8822966484cfSJed Brown [0] 3 4 8823966484cfSJed Brown [0] 4 -6 8824966484cfSJed Brown [1] Number of indices in set 3 8825966484cfSJed Brown [1] 0 2 8826966484cfSJed Brown [1] 1 5 8827966484cfSJed Brown [1] 2 6 8828966484cfSJed Brown ``` 8829966484cfSJed Brown 88301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 88317cd05799SMatthew G. Knepley @*/ 8832d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8833d71ae5a4SJacob Faibussowitsch { 8834ef48cebcSMatthew G. Knepley IS nums[4]; 8835862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8836ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 88370c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8838ef48cebcSMatthew G. Knepley 8839ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8840ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 88420c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 88439566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 88440c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8845862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8846862913ffSStefano Zampini PetscInt end; 8847862913ffSStefano Zampini 8848862913ffSStefano Zampini depths[d] = depth - d; 88499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 88500c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8851862913ffSStefano Zampini } 88520c15888dSMatthew G. Knepley if (empty) 88530c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 88540c15888dSMatthew G. Knepley depths[d] = -1; 88550c15888dSMatthew G. Knepley starts[d] = -1; 88560c15888dSMatthew G. Knepley } 88570c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 88581c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8859ad540459SPierre 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]); 88600c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8861ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8862ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8863ef48cebcSMatthew G. Knepley 88649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 88659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8866ef48cebcSMatthew G. Knepley shift += gsize; 8867ef48cebcSMatthew G. Knepley } 8868d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 88699566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8871ef48cebcSMatthew G. Knepley } 8872ef48cebcSMatthew G. Knepley 887308a22f4bSMatthew G. Knepley /*@ 887408a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 887508a22f4bSMatthew G. Knepley 887608a22f4bSMatthew G. Knepley Input Parameter: 8877a1cb98faSBarry Smith . dm - The `DMPLEX` object 887808a22f4bSMatthew G. Knepley 887908a22f4bSMatthew G. Knepley Output Parameter: 888008a22f4bSMatthew G. Knepley . ranks - The rank field 888108a22f4bSMatthew G. Knepley 8882a1cb98faSBarry Smith Options Database Key: 888320f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 888408a22f4bSMatthew G. Knepley 888508a22f4bSMatthew G. Knepley Level: intermediate 888608a22f4bSMatthew G. Knepley 88871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 888808a22f4bSMatthew G. Knepley @*/ 8889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8890d71ae5a4SJacob Faibussowitsch { 889108a22f4bSMatthew G. Knepley DM rdm; 889208a22f4bSMatthew G. Knepley PetscFE fe; 889308a22f4bSMatthew G. Knepley PetscScalar *r; 889408a22f4bSMatthew G. Knepley PetscMPIInt rank; 8895a55f9a55SMatthew G. Knepley DMPolytopeType ct; 889608a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8897a55f9a55SMatthew G. Knepley PetscBool simplex; 889808a22f4bSMatthew G. Knepley 889908a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8900f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89014f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 89029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 89039566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 89049566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 89059566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 89069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8907a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 89089566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 89099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 89109566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89119566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89129566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89139566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 89149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 89159566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 891608a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 891708a22f4bSMatthew G. Knepley PetscScalar *lr; 891808a22f4bSMatthew G. Knepley 89199566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 892071f09efeSPierre Jolivet if (lr) *lr = rank; 892108a22f4bSMatthew G. Knepley } 89229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 89239566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 892508a22f4bSMatthew G. Knepley } 892608a22f4bSMatthew G. Knepley 8927ca8062c8SMatthew G. Knepley /*@ 892818e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 892918e14f0cSMatthew G. Knepley 893018e14f0cSMatthew G. Knepley Input Parameters: 893120f4b53cSBarry Smith + dm - The `DMPLEX` 893220f4b53cSBarry Smith - label - The `DMLabel` 893318e14f0cSMatthew G. Knepley 893418e14f0cSMatthew G. Knepley Output Parameter: 893518e14f0cSMatthew G. Knepley . val - The label value field 893618e14f0cSMatthew G. Knepley 893720f4b53cSBarry Smith Options Database Key: 893820f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 893918e14f0cSMatthew G. Knepley 894018e14f0cSMatthew G. Knepley Level: intermediate 894118e14f0cSMatthew G. Knepley 89421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 894318e14f0cSMatthew G. Knepley @*/ 8944d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8945d71ae5a4SJacob Faibussowitsch { 894618e14f0cSMatthew G. Knepley DM rdm; 894718e14f0cSMatthew G. Knepley PetscFE fe; 894818e14f0cSMatthew G. Knepley PetscScalar *v; 894918e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 895018e14f0cSMatthew G. Knepley 895118e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 895218e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89534f572ea9SToby Isaac PetscAssertPointer(label, 2); 89544f572ea9SToby Isaac PetscAssertPointer(val, 3); 89559566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 89569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 89579566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 89589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 89599566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89609566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89619566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 89639566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 89649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 89659566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 896618e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 896718e14f0cSMatthew G. Knepley PetscScalar *lv; 896818e14f0cSMatthew G. Knepley PetscInt cval; 896918e14f0cSMatthew G. Knepley 89709566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 89719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 897218e14f0cSMatthew G. Knepley *lv = cval; 897318e14f0cSMatthew G. Knepley } 89749566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 89759566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 897718e14f0cSMatthew G. Knepley } 897818e14f0cSMatthew G. Knepley 897918e14f0cSMatthew G. Knepley /*@ 8980ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8981ca8062c8SMatthew G. Knepley 898269916449SMatthew G. Knepley Input Parameter: 8983a1cb98faSBarry Smith . dm - The `DMPLEX` object 8984a1cb98faSBarry Smith 8985a1cb98faSBarry Smith Level: developer 8986ca8062c8SMatthew G. Knepley 898795eb5ee5SVaclav Hapla Notes: 898895eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 898995eb5ee5SVaclav Hapla 899020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8991ca8062c8SMatthew G. Knepley 89921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8993ca8062c8SMatthew G. Knepley @*/ 8994d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8995d71ae5a4SJacob Faibussowitsch { 8996ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8997ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8998ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 899957beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 900057beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9001ca8062c8SMatthew G. Knepley 9002ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9003ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90049566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 90059566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 90069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9007ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 90089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9009ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 90109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 90119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9012ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 901342e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 901442e66dfaSMatthew G. Knepley PetscInt d; 901542e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 90169371c9d4SSatish Balay if (cone[c] == cone[d]) { 90179371c9d4SSatish Balay dup = PETSC_TRUE; 90189371c9d4SSatish Balay break; 90199371c9d4SSatish Balay } 902042e66dfaSMatthew G. Knepley } 90219566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 90229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9023ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9024ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9025ca8062c8SMatthew G. Knepley } 902642e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 902763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 902848a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 90299566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 903063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 903148a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 90329566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 903363a3b9bcSJacob 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]); 9034f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9035ca8062c8SMatthew G. Knepley } 903642e66dfaSMatthew G. Knepley } 90379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 90389371c9d4SSatish Balay if (p != pp) { 90399371c9d4SSatish Balay storagecheck = PETSC_FALSE; 90409371c9d4SSatish Balay continue; 90419371c9d4SSatish Balay } 90429566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 90439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9044ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 90459566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 90469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9047ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 90489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 90499371c9d4SSatish Balay if (cone[c] != pp) { 90509371c9d4SSatish Balay c = 0; 90519371c9d4SSatish Balay break; 90529371c9d4SSatish Balay } 9053ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9054ca8062c8SMatthew G. Knepley } 9055ca8062c8SMatthew G. Knepley if (c >= coneSize) { 905663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 905748a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 90589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 905963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 906048a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 90619566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 906263a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9063ca8062c8SMatthew G. Knepley } 9064ca8062c8SMatthew G. Knepley } 9065ca8062c8SMatthew G. Knepley } 906657beb4faSStefano Zampini if (storagecheck) { 90679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 90689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 906963a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 907057beb4faSStefano Zampini } 90713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9072ca8062c8SMatthew G. Knepley } 9073ca8062c8SMatthew G. Knepley 9074412e9a14SMatthew G. Knepley /* 9075412e9a14SMatthew 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. 9076412e9a14SMatthew G. Knepley */ 9077d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9078d71ae5a4SJacob Faibussowitsch { 9079412e9a14SMatthew G. Knepley DMPolytopeType cct; 9080412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9081412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9082412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9083412e9a14SMatthew G. Knepley 9084412e9a14SMatthew G. Knepley PetscFunctionBegin; 9085412e9a14SMatthew G. Knepley *unsplit = 0; 9086412e9a14SMatthew G. Knepley switch (ct) { 9087d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9088d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9089d71ae5a4SJacob Faibussowitsch break; 9090412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 90919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9093412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9095412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9096412e9a14SMatthew G. Knepley } 9097412e9a14SMatthew G. Knepley break; 9098412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9099412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 91009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9102412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 91039566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 91049566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9105412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 91069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9107412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9108412e9a14SMatthew G. Knepley PetscInt p; 91099371c9d4SSatish Balay for (p = 0; p < npt; ++p) 91109371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9111412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9112412e9a14SMatthew G. Knepley } 9113412e9a14SMatthew G. Knepley } 9114412e9a14SMatthew G. Knepley } 9115412e9a14SMatthew G. Knepley break; 9116d71ae5a4SJacob Faibussowitsch default: 9117d71ae5a4SJacob Faibussowitsch break; 9118412e9a14SMatthew G. Knepley } 9119412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 91209566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9121412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9122412e9a14SMatthew G. Knepley } 91233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9124412e9a14SMatthew G. Knepley } 9125412e9a14SMatthew G. Knepley 9126ca8062c8SMatthew G. Knepley /*@ 9127ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9128ca8062c8SMatthew G. Knepley 9129ca8062c8SMatthew G. Knepley Input Parameters: 9130a1cb98faSBarry Smith + dm - The `DMPLEX` object 913158723a97SMatthew G. Knepley - cellHeight - Normally 0 9132ca8062c8SMatthew G. Knepley 9133a1cb98faSBarry Smith Level: developer 9134a1cb98faSBarry Smith 913595eb5ee5SVaclav Hapla Notes: 913695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 913725c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9138ca8062c8SMatthew G. Knepley 913920f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 914095eb5ee5SVaclav Hapla 91411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9142ca8062c8SMatthew G. Knepley @*/ 9143d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9144d71ae5a4SJacob Faibussowitsch { 9145412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9146412e9a14SMatthew G. Knepley DMPolytopeType ct; 9147412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9148ca8062c8SMatthew G. Knepley 9149ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9150ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91519566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 91529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 91539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9154412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9155412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9156412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 915758723a97SMatthew G. Knepley 91589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 915963a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9160412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9161412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 91629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 916363a3b9bcSJacob 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)); 9164412e9a14SMatthew G. Knepley } 91659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 916658723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 916758723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9168412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 916958723a97SMatthew G. Knepley } 91709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9171412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9172412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9173412e9a14SMatthew G. Knepley PetscInt unsplit; 917442363296SMatthew G. Knepley 91759566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9176412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 917742363296SMatthew G. Knepley } 917863a3b9bcSJacob 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)); 917942363296SMatthew G. Knepley } 91803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9181ca8062c8SMatthew G. Knepley } 91829bf0dad6SMatthew G. Knepley 91839bf0dad6SMatthew G. Knepley /*@ 91849bf0dad6SMatthew 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 91859bf0dad6SMatthew G. Knepley 918620f4b53cSBarry Smith Collective 9187899ea2b8SJacob Faibussowitsch 91889bf0dad6SMatthew G. Knepley Input Parameters: 9189a1cb98faSBarry Smith + dm - The `DMPLEX` object 91909bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 91919bf0dad6SMatthew G. Knepley 9192a1cb98faSBarry Smith Level: developer 9193a1cb98faSBarry Smith 919445da879fSVaclav Hapla Notes: 919545da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 919645da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 919745da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 919845da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 91999bf0dad6SMatthew G. Knepley 9200a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 920195eb5ee5SVaclav Hapla 92021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 92039bf0dad6SMatthew G. Knepley @*/ 9204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9205d71ae5a4SJacob Faibussowitsch { 9206ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9207899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 92089bf0dad6SMatthew G. Knepley 92099bf0dad6SMatthew G. Knepley PetscFunctionBegin; 92109bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92118f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 92123ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 92138f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 92143ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 92153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9216899ea2b8SJacob Faibussowitsch } 9217899ea2b8SJacob Faibussowitsch 92189566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 92209566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9221ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 92229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 92233554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9224412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9225412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9226ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9227412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9228412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 92299bf0dad6SMatthew G. Knepley 92309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 92319566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9232412e9a14SMatthew G. Knepley if (unsplit) continue; 92339566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 92349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 92359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 92369566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92379bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 92389bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 92399bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 92409bf0dad6SMatthew G. Knepley } 92419566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 924263a3b9bcSJacob 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); 92439bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9244d4961f80SStefano Zampini DMPolytopeType fct; 92459bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 92469bf0dad6SMatthew G. Knepley 92479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 92489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 92499bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 92509bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 92519bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 92529bf0dad6SMatthew G. Knepley } 925363a3b9bcSJacob 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]); 92549bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9255b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9256b5a892a1SMatthew G. Knepley PetscInt v1; 9257b5a892a1SMatthew G. Knepley 92589566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 925963a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 92609566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 926163a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 92629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 926363a3b9bcSJacob 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]); 9264b5a892a1SMatthew G. Knepley } 92659bf0dad6SMatthew G. Knepley } 92669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9267412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 92689bf0dad6SMatthew G. Knepley } 92699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92719bf0dad6SMatthew G. Knepley } 92723554e41dSMatthew G. Knepley } 92733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9274552f7358SJed Brown } 92753913d7c8SMatthew G. Knepley 9276bb6a34a8SMatthew G. Knepley /*@ 9277bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9278bb6a34a8SMatthew G. Knepley 9279bb6a34a8SMatthew G. Knepley Input Parameter: 9280a1cb98faSBarry Smith . dm - The `DMPLEX` object 9281a1cb98faSBarry Smith 9282a1cb98faSBarry Smith Level: developer 9283bb6a34a8SMatthew G. Knepley 928495eb5ee5SVaclav Hapla Notes: 928595eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 928695eb5ee5SVaclav Hapla 928720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9288bb6a34a8SMatthew G. Knepley 92891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9290bb6a34a8SMatthew G. Knepley @*/ 9291d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9292d71ae5a4SJacob Faibussowitsch { 9293a2a9e04cSMatthew G. Knepley Vec coordinates; 9294bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9295bb6a34a8SMatthew G. Knepley PetscReal vol; 929651a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9297bb6a34a8SMatthew G. Knepley 9298bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 92999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 93009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 93013ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 93029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9303bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 93049566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9305a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 93069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 93073ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9308412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9309412e9a14SMatthew G. Knepley DMPolytopeType ct; 9310412e9a14SMatthew G. Knepley PetscInt unsplit; 9311412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9312412e9a14SMatthew G. Knepley 93139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9314412e9a14SMatthew G. Knepley switch (ct) { 9315412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9316412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9317d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9318d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9319d71ae5a4SJacob Faibussowitsch break; 9320d71ae5a4SJacob Faibussowitsch default: 9321d71ae5a4SJacob Faibussowitsch break; 9322412e9a14SMatthew G. Knepley } 9323412e9a14SMatthew G. Knepley switch (ct) { 9324412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9325412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9326412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9327d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9328d71ae5a4SJacob Faibussowitsch continue; 9329d71ae5a4SJacob Faibussowitsch default: 9330d71ae5a4SJacob Faibussowitsch break; 9331412e9a14SMatthew G. Knepley } 93329566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9333412e9a14SMatthew G. Knepley if (unsplit) continue; 93349566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 93351dca8a05SBarry 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); 933663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 93376858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 93386858538eSMatthew G. Knepley if (depth > 1) { 93399566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 93401dca8a05SBarry 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); 934163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9342bb6a34a8SMatthew G. Knepley } 9343bb6a34a8SMatthew G. Knepley } 93443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9345bb6a34a8SMatthew G. Knepley } 9346bb6a34a8SMatthew G. Knepley 934703da9461SVaclav Hapla /*@ 934820f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 93497726db96SVaclav Hapla 935020f4b53cSBarry Smith Collective 935103da9461SVaclav Hapla 935203da9461SVaclav Hapla Input Parameters: 9353a1cb98faSBarry Smith + dm - The `DMPLEX` object 935420f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9355a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9356a1cb98faSBarry Smith 9357a1cb98faSBarry Smith Level: developer 935803da9461SVaclav Hapla 9359e83a0d2dSVaclav Hapla Notes: 9360e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 936103da9461SVaclav Hapla 9362a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 936395eb5ee5SVaclav Hapla 9364baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9365d7d32a9aSMatthew G. Knepley 93661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 936703da9461SVaclav Hapla @*/ 9368d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9369d71ae5a4SJacob Faibussowitsch { 93707726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93717726db96SVaclav Hapla const PetscInt *locals; 93727726db96SVaclav Hapla const PetscSFNode *remotes; 9373f0cfc026SVaclav Hapla PetscBool distributed; 93747726db96SVaclav Hapla MPI_Comm comm; 93757726db96SVaclav Hapla PetscMPIInt rank; 937603da9461SVaclav Hapla 937703da9461SVaclav Hapla PetscFunctionBegin; 937803da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93797726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 93807726db96SVaclav Hapla else pointSF = dm->sf; 93817726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93827726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 93837726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 93847726db96SVaclav Hapla { 93857726db96SVaclav Hapla PetscMPIInt mpiFlag; 93867726db96SVaclav Hapla 93877726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 93887726db96SVaclav 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); 93897726db96SVaclav Hapla } 93907726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 93919566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 93927726db96SVaclav Hapla if (!distributed) { 93937726db96SVaclav 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); 93943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93958918e3e2SVaclav Hapla } 93967726db96SVaclav 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); 93977726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 939803da9461SVaclav Hapla 93997726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 94007726db96SVaclav Hapla { 94017726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 94027726db96SVaclav Hapla 94037726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 94047726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9405d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 94067726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 94077726db96SVaclav Hapla } 94087726db96SVaclav Hapla 94097726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 94107726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 94117726db96SVaclav 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); 94127726db96SVaclav Hapla } 94137726db96SVaclav Hapla 94147726db96SVaclav Hapla /* Check there are no cells in interface */ 94157726db96SVaclav Hapla if (!overlap) { 94167726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 94177726db96SVaclav Hapla 94189566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94199566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9420f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94217726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9422f5869d18SMatthew G. Knepley 94237726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 94247726db96SVaclav Hapla } 942503da9461SVaclav Hapla } 9426ece87651SVaclav Hapla 94277726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 94287726db96SVaclav Hapla { 94297726db96SVaclav Hapla const PetscInt *rootdegree; 94307726db96SVaclav Hapla 94317726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 94327726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9433f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94347726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9435f5869d18SMatthew G. Knepley const PetscInt *cone; 9436f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9437f5869d18SMatthew G. Knepley 94389566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 94399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9440f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9441f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 94427726db96SVaclav Hapla if (locals) { 94439566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 94447726db96SVaclav Hapla } else { 94457726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 94467726db96SVaclav Hapla } 944763a3b9bcSJacob 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]); 9448f5869d18SMatthew G. Knepley } 9449f5869d18SMatthew G. Knepley } 9450ece87651SVaclav Hapla } 94517726db96SVaclav Hapla } 94523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 945303da9461SVaclav Hapla } 945403da9461SVaclav Hapla 94557f9d8d6cSVaclav Hapla /*@ 945620f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 94577f9d8d6cSVaclav Hapla 94587f9d8d6cSVaclav Hapla Input Parameter: 9459a1cb98faSBarry Smith . dm - The `DMPLEX` object 9460a1cb98faSBarry Smith 9461a1cb98faSBarry Smith Level: developer 94627f9d8d6cSVaclav Hapla 94637f9d8d6cSVaclav Hapla Notes: 94647f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 94657f9d8d6cSVaclav Hapla 946620f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 94677f9d8d6cSVaclav Hapla 946820f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94697f9d8d6cSVaclav Hapla 94701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94717f9d8d6cSVaclav Hapla @*/ 9472d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9473d71ae5a4SJacob Faibussowitsch { 94747f9d8d6cSVaclav Hapla PetscInt cellHeight; 94757f9d8d6cSVaclav Hapla 9476b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94777f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94789566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 94799566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 94809566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 94819566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9482d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 94839566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 94843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9485b5a892a1SMatthew G. Knepley } 9486b5a892a1SMatthew G. Knepley 94879371c9d4SSatish Balay typedef struct cell_stats { 9488068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9489068a5610SStefano Zampini PetscInt count; 9490068a5610SStefano Zampini } cell_stats_t; 9491068a5610SStefano Zampini 9492d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9493d71ae5a4SJacob Faibussowitsch { 9494068a5610SStefano Zampini PetscInt i, N = *len; 9495068a5610SStefano Zampini 9496068a5610SStefano Zampini for (i = 0; i < N; i++) { 9497068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9498068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9499068a5610SStefano Zampini 9500068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9501068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9502068a5610SStefano Zampini B->sum += A->sum; 9503068a5610SStefano Zampini B->squaresum += A->squaresum; 9504068a5610SStefano Zampini B->count += A->count; 9505068a5610SStefano Zampini } 9506068a5610SStefano Zampini } 9507068a5610SStefano Zampini 9508068a5610SStefano Zampini /*@ 950943fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9510068a5610SStefano Zampini 951120f4b53cSBarry Smith Collective 95128261a58bSMatthew G. Knepley 9513068a5610SStefano Zampini Input Parameters: 9514a1cb98faSBarry Smith + dm - The `DMPLEX` object 951520f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9516a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9517a1cb98faSBarry Smith 9518a1cb98faSBarry Smith Level: developer 9519068a5610SStefano Zampini 952095eb5ee5SVaclav Hapla Notes: 952195eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 952295eb5ee5SVaclav Hapla 9523a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9524068a5610SStefano Zampini 95251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9526068a5610SStefano Zampini @*/ 9527d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9528d71ae5a4SJacob Faibussowitsch { 9529068a5610SStefano Zampini DM dmCoarse; 953043fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 953143fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 953243fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 953343fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9534412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 953543fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9536068a5610SStefano Zampini 9537068a5610SStefano Zampini PetscFunctionBegin; 9538068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9539068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9540068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9541068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9542068a5610SStefano Zampini stats.count = 0; 9543068a5610SStefano Zampini 95449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 95459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 95469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 95479566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 95489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 95499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9550412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9551068a5610SStefano Zampini PetscInt i; 9552068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9553068a5610SStefano Zampini 95549566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 955563a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 955643fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9557068a5610SStefano Zampini frobJ += J[i] * J[i]; 9558068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9559068a5610SStefano Zampini } 9560068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9561068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9562068a5610SStefano Zampini 9563068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9564068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9565068a5610SStefano Zampini stats.sum += cond; 9566068a5610SStefano Zampini stats.squaresum += cond2; 9567068a5610SStefano Zampini stats.count++; 95688261a58bSMatthew G. Knepley if (output && cond > limit) { 956943fa8764SMatthew G. Knepley PetscSection coordSection; 957043fa8764SMatthew G. Knepley Vec coordsLocal; 957143fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 957243fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 957343fa8764SMatthew G. Knepley 95749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95769566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 957763a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 957843fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 957963a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 958043fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 95819566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 95829566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 958343fa8764SMatthew G. Knepley } 95849566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 958543fa8764SMatthew G. Knepley } 95869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 958743fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 958843fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 958943fa8764SMatthew G. Knepley 959043fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 959143fa8764SMatthew G. Knepley PetscReal len; 959243fa8764SMatthew G. Knepley 95939566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 959463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 959543fa8764SMatthew G. Knepley } 959643fa8764SMatthew G. Knepley } 95979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 95989566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 959943fa8764SMatthew G. Knepley } 9600068a5610SStefano Zampini } 96019566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9602068a5610SStefano Zampini 9603068a5610SStefano Zampini if (size > 1) { 9604068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9605068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9606068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9607068a5610SStefano Zampini MPI_Op statReduce; 9608068a5610SStefano Zampini 96099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 96109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 96119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 96129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 96139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 96149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9615068a5610SStefano Zampini } else { 96169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9617068a5610SStefano Zampini } 9618dd400576SPatrick Sanan if (rank == 0) { 9619068a5610SStefano Zampini count = globalStats.count; 9620068a5610SStefano Zampini min = globalStats.min; 9621068a5610SStefano Zampini max = globalStats.max; 9622068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9623068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9624068a5610SStefano Zampini } 9625068a5610SStefano Zampini 962648a46eb9SPierre 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)); 96279566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9628068a5610SStefano Zampini 96299566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9630068a5610SStefano Zampini if (dmCoarse) { 9631068a5610SStefano Zampini PetscBool isplex; 9632068a5610SStefano Zampini 96339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 96341baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9635068a5610SStefano Zampini } 96363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9637068a5610SStefano Zampini } 9638068a5610SStefano Zampini 9639f108dbd7SJacob Faibussowitsch /*@ 9640f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9641f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9642f108dbd7SJacob Faibussowitsch 964320f4b53cSBarry Smith Collective 9644f108dbd7SJacob Faibussowitsch 9645f108dbd7SJacob Faibussowitsch Input Parameters: 9646a1cb98faSBarry Smith + dm - The `DMPLEX` object 9647a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9648f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9649f108dbd7SJacob Faibussowitsch 9650f108dbd7SJacob Faibussowitsch Output Parameters: 965120f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9652a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9653f108dbd7SJacob Faibussowitsch 9654f108dbd7SJacob Faibussowitsch Options Database Keys: 9655a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9656f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9657f108dbd7SJacob Faibussowitsch 9658a1cb98faSBarry Smith Level: intermediate 9659a1cb98faSBarry Smith 9660f108dbd7SJacob Faibussowitsch Notes: 9661a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9662f108dbd7SJacob Faibussowitsch 9663a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9664f108dbd7SJacob Faibussowitsch 9665f108dbd7SJacob 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 9666f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9667f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9668f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9669f108dbd7SJacob Faibussowitsch 9670f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9671f108dbd7SJacob Faibussowitsch 9672a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9673f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9674f108dbd7SJacob Faibussowitsch 9675f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9676f108dbd7SJacob Faibussowitsch 96771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9678f108dbd7SJacob Faibussowitsch @*/ 9679d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9680d71ae5a4SJacob Faibussowitsch { 96816ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 96826ed19f2fSJacob Faibussowitsch PetscInt *idx; 96836ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9684f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 96856ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9686f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9687f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9688f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9689f108dbd7SJacob Faibussowitsch IS glob; 9690f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9691f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9692f108dbd7SJacob Faibussowitsch 9693f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9694f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9695ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 96964f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 96976bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 96989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 96999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 970063a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 97016ed19f2fSJacob Faibussowitsch { 97026ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 97036ed19f2fSJacob Faibussowitsch 97049566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9705f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9706f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9707f108dbd7SJacob Faibussowitsch 97089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 970998921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9710f108dbd7SJacob Faibussowitsch } 97116ed19f2fSJacob Faibussowitsch } 9712f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97134f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 97149566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 97159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 97169371c9d4SSatish Balay } else { 97179371c9d4SSatish Balay *OrthQualLabel = NULL; 97189371c9d4SSatish Balay } 97199566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 97219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 97229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 97239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 97249566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 97259566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 97269566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 97279566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 97289566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 97299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 97309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 97319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 97329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 97339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 97349566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 97359566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 97369566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 97376ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 97386ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9739f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9740f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9741898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9742f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9743f108dbd7SJacob Faibussowitsch 97446ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9745f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9746f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 97479566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 97489566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9749f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 97509566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 97516ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 97526ed19f2fSJacob Faibussowitsch PetscInt i; 97536ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9754f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9755f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9756f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9757f108dbd7SJacob Faibussowitsch 9758f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9759f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 97609566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9761f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 97626ed19f2fSJacob Faibussowitsch { 97636ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 97646ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 97656ed19f2fSJacob Faibussowitsch 97669566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97679566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 97689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97696ed19f2fSJacob Faibussowitsch } 9770f108dbd7SJacob Faibussowitsch 9771f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9772f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9773f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9774f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9775f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9776addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9777addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9778addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9779f108dbd7SJacob Faibussowitsch } 9780addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9781addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9782addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9783f108dbd7SJacob Faibussowitsch 9784f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9785f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9786f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9787f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9788f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9789f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9790f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9791f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9792f108dbd7SJacob Faibussowitsch } 9793ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9794ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9795f108dbd7SJacob Faibussowitsch } 97969566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 97979566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9798f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 97996ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9800f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98019566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9802f108dbd7SJacob Faibussowitsch } 9803f108dbd7SJacob Faibussowitsch } 98049566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 98059566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 98069566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 98079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 98089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 98099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9810f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98119566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9812f108dbd7SJacob Faibussowitsch } 98139566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9814cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 98159566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 98163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9817f108dbd7SJacob Faibussowitsch } 9818f108dbd7SJacob Faibussowitsch 9819d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 98201eb70e55SToby Isaac * interpolator construction */ 9821d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9822d71ae5a4SJacob Faibussowitsch { 98231eb70e55SToby Isaac PetscSection section, newSection, gsection; 98241eb70e55SToby Isaac PetscSF sf; 98251eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 98261eb70e55SToby Isaac 98271eb70e55SToby Isaac PetscFunctionBegin; 98281eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98294f572ea9SToby Isaac PetscAssertPointer(odm, 2); 98309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 98319566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9832712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 98331eb70e55SToby Isaac if (!ghasConstraints) { 98349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 98351eb70e55SToby Isaac *odm = dm; 98363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98371eb70e55SToby Isaac } 98389566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 98399566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 98409566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 98419566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 98429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 98439566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 98449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 98453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98461eb70e55SToby Isaac } 98471eb70e55SToby Isaac 9848d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9849d71ae5a4SJacob Faibussowitsch { 98501eb70e55SToby Isaac DM dmco, dmfo; 98511eb70e55SToby Isaac Mat interpo; 98521eb70e55SToby Isaac Vec rscale; 98531eb70e55SToby Isaac Vec cglobalo, clocal; 98541eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 98551eb70e55SToby Isaac PetscBool regular; 98561eb70e55SToby Isaac 98571eb70e55SToby Isaac PetscFunctionBegin; 98589566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 98599566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 98609566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 98619566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 98629566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 98639566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 98649566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 98659566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 98669566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 98679566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 98689566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98699566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98709566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98719566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98729566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98739566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98749566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98759566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98769566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98779566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 98789566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 98799566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 98809566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 98819566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 98821eb70e55SToby Isaac *shift = fglobal; 98839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 98849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 98859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 98869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 98879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 98899566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 98909566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 98913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98921eb70e55SToby Isaac } 98931eb70e55SToby Isaac 9894d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9895d71ae5a4SJacob Faibussowitsch { 98961eb70e55SToby Isaac PetscObject shifto; 98971eb70e55SToby Isaac Vec shift; 98981eb70e55SToby Isaac 98991eb70e55SToby Isaac PetscFunctionBegin; 99001eb70e55SToby Isaac if (!interp) { 99011eb70e55SToby Isaac Vec rscale; 99021eb70e55SToby Isaac 99039566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 99049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 99051eb70e55SToby Isaac } else { 99069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 99071eb70e55SToby Isaac } 99089566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 99091eb70e55SToby Isaac if (!shifto) { 99109566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 99119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 99121eb70e55SToby Isaac shifto = (PetscObject)shift; 99139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 99141eb70e55SToby Isaac } 99151eb70e55SToby Isaac shift = (Vec)shifto; 99169566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 99179566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 99189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 99193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99201eb70e55SToby Isaac } 99211eb70e55SToby Isaac 9922bceba477SMatthew G. Knepley /* Pointwise interpolation 9923bceba477SMatthew G. Knepley Just code FEM for now 9924bceba477SMatthew G. Knepley u^f = I u^c 99254ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 99264ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 99274ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9928bceba477SMatthew G. Knepley */ 9929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9930d71ae5a4SJacob Faibussowitsch { 9931bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9932bceba477SMatthew G. Knepley PetscInt m, n; 9933a063dac3SMatthew G. Knepley void *ctx; 993468132eb9SMatthew G. Knepley DM cdm; 9935cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9936bceba477SMatthew G. Knepley 9937bceba477SMatthew G. Knepley PetscFunctionBegin; 99389566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 99399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 99409566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 99419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 994268132eb9SMatthew G. Knepley 99439566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 99449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 99459566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 99469566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 99479566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 994868132eb9SMatthew G. Knepley 99499566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99509566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99519566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 99529566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 99539566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 99544db47ee9SStefano Zampini if (scaling) { 99555d1c2e58SMatthew G. Knepley /* Use naive scaling */ 99569566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 99574db47ee9SStefano Zampini } 99583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9959a063dac3SMatthew G. Knepley } 9960bceba477SMatthew G. Knepley 9961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9962d71ae5a4SJacob Faibussowitsch { 99636dbf9973SLawrence Mitchell VecScatter ctx; 996490748bafSMatthew G. Knepley 9965a063dac3SMatthew G. Knepley PetscFunctionBegin; 99669566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 99679566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 99689566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9970bceba477SMatthew G. Knepley } 9971bceba477SMatthew G. Knepley 9972d71ae5a4SJacob 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[]) 9973d71ae5a4SJacob Faibussowitsch { 997400635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 997500635df3SMatthew G. Knepley PetscInt c; 997600635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99773e9753d6SMatthew G. Knepley } 99783e9753d6SMatthew G. Knepley 9979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9980d71ae5a4SJacob Faibussowitsch { 9981b4937a87SMatthew G. Knepley DM dmc; 9982b4937a87SMatthew G. Knepley PetscDS ds; 9983b4937a87SMatthew G. Knepley Vec ones, locmass; 9984b4937a87SMatthew G. Knepley IS cellIS; 9985b4937a87SMatthew G. Knepley PetscFormKey key; 9986b4937a87SMatthew G. Knepley PetscInt depth; 9987b4937a87SMatthew G. Knepley 9988b4937a87SMatthew G. Knepley PetscFunctionBegin; 99899566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 99909566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 99919566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99929566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99939566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 99949566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 99959566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 99969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99979566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99989566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 99999566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10000b4937a87SMatthew G. Knepley key.label = NULL; 10001b4937a87SMatthew G. Knepley key.value = 0; 10002b4937a87SMatthew G. Knepley key.field = 0; 10003b4937a87SMatthew G. Knepley key.part = 0; 100049566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 100059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100069566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 100079566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 100089566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 100099566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 100109566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 100119566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10013b4937a87SMatthew G. Knepley } 10014b4937a87SMatthew G. Knepley 10015d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10016d71ae5a4SJacob Faibussowitsch { 10017bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10018bd041c0cSMatthew G. Knepley PetscInt m, n; 10019bd041c0cSMatthew G. Knepley void *ctx; 10020bd041c0cSMatthew G. Knepley DM cdm; 10021bd041c0cSMatthew G. Knepley PetscBool regular; 10022bd041c0cSMatthew G. Knepley 10023bd041c0cSMatthew G. Knepley PetscFunctionBegin; 100243e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 100253e9753d6SMatthew G. Knepley DM dmc; 100263e9753d6SMatthew G. Knepley PetscDS ds; 10027b4937a87SMatthew G. Knepley PetscWeakForm wf; 100283e9753d6SMatthew G. Knepley Vec u; 100293e9753d6SMatthew G. Knepley IS cellIS; 1003006ad1575SMatthew G. Knepley PetscFormKey key; 100313e9753d6SMatthew G. Knepley PetscInt depth; 100323e9753d6SMatthew G. Knepley 100339566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 100349566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 100359566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 100369566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 100379566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 100389566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 100399566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 100408d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 100419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 100429566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 100439566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 100446528b96dSMatthew G. Knepley key.label = NULL; 100456528b96dSMatthew G. Knepley key.value = 0; 100466528b96dSMatthew G. Knepley key.field = 0; 1004706ad1575SMatthew G. Knepley key.part = 0; 100489566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 100499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100508d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 100519566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100523e9753d6SMatthew G. Knepley } else { 100539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 100549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 100559566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 100569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10057bd041c0cSMatthew G. Knepley 100589566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 100599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 100609566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 100619566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10062bd041c0cSMatthew G. Knepley 100639566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 100649566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 100659566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 100669566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 100673e9753d6SMatthew G. Knepley } 100689566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10070bd041c0cSMatthew G. Knepley } 10071bd041c0cSMatthew G. Knepley 100720aef6b92SMatthew G. Knepley /*@ 100730aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100740aef6b92SMatthew G. Knepley 100750aef6b92SMatthew G. Knepley Input Parameter: 10076a1cb98faSBarry Smith . dm - The `DMPLEX` object 100770aef6b92SMatthew G. Knepley 100780aef6b92SMatthew G. Knepley Output Parameter: 100790aef6b92SMatthew G. Knepley . regular - The flag 100800aef6b92SMatthew G. Knepley 100810aef6b92SMatthew G. Knepley Level: intermediate 100820aef6b92SMatthew G. Knepley 100831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 100840aef6b92SMatthew G. Knepley @*/ 10085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10086d71ae5a4SJacob Faibussowitsch { 100870aef6b92SMatthew G. Knepley PetscFunctionBegin; 100880aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100894f572ea9SToby Isaac PetscAssertPointer(regular, 2); 100900aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 100913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100920aef6b92SMatthew G. Knepley } 100930aef6b92SMatthew G. Knepley 100940aef6b92SMatthew G. Knepley /*@ 100950aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100960aef6b92SMatthew G. Knepley 100970aef6b92SMatthew G. Knepley Input Parameters: 10098a1cb98faSBarry Smith + dm - The `DMPLEX` object 100990aef6b92SMatthew G. Knepley - regular - The flag 101000aef6b92SMatthew G. Knepley 101010aef6b92SMatthew G. Knepley Level: intermediate 101020aef6b92SMatthew G. Knepley 101031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 101040aef6b92SMatthew G. Knepley @*/ 10105d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10106d71ae5a4SJacob Faibussowitsch { 101070aef6b92SMatthew G. Knepley PetscFunctionBegin; 101080aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101090aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 101103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101110aef6b92SMatthew G. Knepley } 101120aef6b92SMatthew G. Knepley 10113a68b90caSToby Isaac /*@ 10114f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10115a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10116a68b90caSToby Isaac 10117a1cb98faSBarry Smith Not Collective 10118a68b90caSToby Isaac 10119f899ff85SJose E. Roman Input Parameter: 10120a1cb98faSBarry Smith . dm - The `DMPLEX` object 10121a68b90caSToby Isaac 10122a68b90caSToby Isaac Output Parameters: 1012320f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1012420f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10125a68b90caSToby Isaac 10126a68b90caSToby Isaac Level: intermediate 10127a68b90caSToby Isaac 101281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10129a68b90caSToby Isaac @*/ 10130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10131d71ae5a4SJacob Faibussowitsch { 10132a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10133a68b90caSToby Isaac 10134a68b90caSToby Isaac PetscFunctionBegin; 10135a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101369566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10137a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10138a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 101393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10140a68b90caSToby Isaac } 10141a68b90caSToby Isaac 10142a68b90caSToby Isaac /*@ 10143a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10144a68b90caSToby Isaac 1014520f4b53cSBarry Smith Collective 10146a68b90caSToby Isaac 10147a68b90caSToby Isaac Input Parameters: 10148a1cb98faSBarry Smith + dm - The `DMPLEX` object 10149a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10150a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10151a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10152a68b90caSToby Isaac 10153a68b90caSToby Isaac Level: intermediate 10154a68b90caSToby Isaac 10155a1cb98faSBarry Smith Notes: 10156a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10157a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10158a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10159a4e35b19SJacob Faibussowitsch 10160a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10161a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10162a1cb98faSBarry Smith 1016320f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10164a1cb98faSBarry Smith 101651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10166a68b90caSToby Isaac @*/ 10167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10168d71ae5a4SJacob Faibussowitsch { 10169a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10170e228b242SToby Isaac PetscMPIInt result; 10171a68b90caSToby Isaac 10172a68b90caSToby Isaac PetscFunctionBegin; 10173a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10174e228b242SToby Isaac if (anchorSection) { 10175e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101771dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10178e228b242SToby Isaac } 10179e228b242SToby Isaac if (anchorIS) { 10180e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 101819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 101821dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10183e228b242SToby Isaac } 10184a68b90caSToby Isaac 101859566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 101869566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10187a68b90caSToby Isaac plex->anchorSection = anchorSection; 10188a68b90caSToby Isaac 101899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 101909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10191a68b90caSToby Isaac plex->anchorIS = anchorIS; 10192a68b90caSToby Isaac 10193cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10194a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10195a68b90caSToby Isaac const PetscInt *anchors; 10196a68b90caSToby Isaac 101979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 101999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10200a68b90caSToby Isaac for (a = 0; a < size; a++) { 10201a68b90caSToby Isaac PetscInt p; 10202a68b90caSToby Isaac 10203a68b90caSToby Isaac p = anchors[a]; 10204a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10205a68b90caSToby Isaac PetscInt dof; 10206a68b90caSToby Isaac 102079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10208a68b90caSToby Isaac if (dof) { 102099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1021063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10211a68b90caSToby Isaac } 10212a68b90caSToby Isaac } 10213a68b90caSToby Isaac } 102149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10215a68b90caSToby Isaac } 10216f7c74593SToby Isaac /* reset the generic constraints */ 102179566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 102183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10219a68b90caSToby Isaac } 10220a68b90caSToby Isaac 10221d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10222d71ae5a4SJacob Faibussowitsch { 10223f7c74593SToby Isaac PetscSection anchorSection; 102246995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10225a68b90caSToby Isaac 10226a68b90caSToby Isaac PetscFunctionBegin; 10227a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102289566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 102299566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 102309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102316995de1eSToby Isaac if (numFields) { 10232719ab38cSToby Isaac PetscInt f; 102339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10234719ab38cSToby Isaac 10235719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10236719ab38cSToby Isaac PetscInt numComp; 10237719ab38cSToby Isaac 102389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 102399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10240719ab38cSToby Isaac } 102416995de1eSToby Isaac } 102429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 102439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102446995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 102456995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 102466995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 102479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10248a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 102499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10250a68b90caSToby Isaac if (dof) { 102519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 102529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10253a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 102549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 102559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10256a68b90caSToby Isaac } 10257a68b90caSToby Isaac } 10258a68b90caSToby Isaac } 102599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 102609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 102613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10262a68b90caSToby Isaac } 10263a68b90caSToby Isaac 10264d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10265d71ae5a4SJacob Faibussowitsch { 10266f7c74593SToby Isaac PetscSection aSec; 10267ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 102680ac89760SToby Isaac const PetscInt *anchors; 102690ac89760SToby Isaac PetscInt numFields, f; 1027066ad2231SToby Isaac IS aIS; 10271e19f7ee6SMark Adams MatType mtype; 10272e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102730ac89760SToby Isaac 102740ac89760SToby Isaac PetscFunctionBegin; 102750ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 102789566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 102799566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 102809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 102819566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 102829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 102839566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10284e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10285e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10286e19f7ee6SMark Adams else mtype = MATSEQAIJ; 102879566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 102889566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 102899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 102906995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 102919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 102929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 102940ac89760SToby Isaac i[0] = 0; 102959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102960ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10297f19733c5SToby Isaac PetscInt rDof, rOff, r; 10298f19733c5SToby Isaac 102999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10300f19733c5SToby Isaac if (!rDof) continue; 103019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103020ac89760SToby Isaac if (numFields) { 103030ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103040ac89760SToby Isaac annz = 0; 10305f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10306f19733c5SToby Isaac a = anchors[rOff + r]; 10307ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103090ac89760SToby Isaac annz += aDof; 103100ac89760SToby Isaac } 103119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10313ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103140ac89760SToby Isaac } 103152f7452b8SBarry Smith } else { 103160ac89760SToby Isaac annz = 0; 103179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103180ac89760SToby Isaac for (q = 0; q < dof; q++) { 10319ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10320ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103220ac89760SToby Isaac annz += aDof; 103230ac89760SToby Isaac } 103249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10326ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103270ac89760SToby Isaac } 103280ac89760SToby Isaac } 103290ac89760SToby Isaac nnz = i[m]; 103309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 103310ac89760SToby Isaac offset = 0; 103320ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 103330ac89760SToby Isaac if (numFields) { 103340ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103360ac89760SToby Isaac for (q = 0; q < dof; q++) { 103370ac89760SToby Isaac PetscInt rDof, rOff, r; 103389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103400ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103410ac89760SToby Isaac PetscInt s; 103420ac89760SToby Isaac 103430ac89760SToby Isaac a = anchors[rOff + r]; 10344ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10347ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103480ac89760SToby Isaac } 103490ac89760SToby Isaac } 103500ac89760SToby Isaac } 103512f7452b8SBarry Smith } else { 103529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103530ac89760SToby Isaac for (q = 0; q < dof; q++) { 103540ac89760SToby Isaac PetscInt rDof, rOff, r; 103559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103570ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103580ac89760SToby Isaac PetscInt s; 103590ac89760SToby Isaac 103600ac89760SToby Isaac a = anchors[rOff + r]; 10361ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10364ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103650ac89760SToby Isaac } 103660ac89760SToby Isaac } 103670ac89760SToby Isaac } 103680ac89760SToby Isaac } 103699566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103709566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103719566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103740ac89760SToby Isaac } 103750ac89760SToby Isaac 10376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10377d71ae5a4SJacob Faibussowitsch { 10378f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10379f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1038066ad2231SToby Isaac Mat cMat; 1038166ad2231SToby Isaac 1038266ad2231SToby Isaac PetscFunctionBegin; 1038366ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103849566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1038566ad2231SToby Isaac if (anchorSection) { 1038644a7f3ddSMatthew G. Knepley PetscInt Nf; 10387e228b242SToby Isaac 103889566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 103899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 103909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 103919566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 103929566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 103939566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 103949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 103959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1039666ad2231SToby Isaac } 103973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1039866ad2231SToby Isaac } 10399a93c429eSMatthew G. Knepley 10400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10401d71ae5a4SJacob Faibussowitsch { 10402a93c429eSMatthew G. Knepley IS subis; 10403a93c429eSMatthew G. Knepley PetscSection section, subsection; 10404a93c429eSMatthew G. Knepley 10405a93c429eSMatthew G. Knepley PetscFunctionBegin; 104069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1040728b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1040828b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10409a93c429eSMatthew G. Knepley /* Create subdomain */ 104109566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10411a93c429eSMatthew G. Knepley /* Create submodel */ 104129566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 104139566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 104149566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 104159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 104169566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10417a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10418a93c429eSMatthew G. Knepley if (is) { 10419a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10420a93c429eSMatthew G. Knepley IS spIS; 10421a93c429eSMatthew G. Knepley const PetscInt *spmap; 10422a93c429eSMatthew G. Knepley PetscInt *subIndices; 10423a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10424a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10425a93c429eSMatthew G. Knepley 104269566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 104279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 104289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 104299566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 104309566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 104319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10432a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10433a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10434a93c429eSMatthew G. Knepley 104359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10436a93c429eSMatthew G. Knepley if (gdof > 0) { 10437a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10438a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10439a93c429eSMatthew G. Knepley 104409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 104419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10442a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10443a93c429eSMatthew G. Knepley } 10444a93c429eSMatthew G. Knepley subSize += pSubSize; 10445a93c429eSMatthew G. Knepley if (pSubSize) { 10446a93c429eSMatthew G. Knepley if (bs < 0) { 10447a93c429eSMatthew G. Knepley bs = pSubSize; 10448a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10449a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10450a93c429eSMatthew G. Knepley bs = 1; 10451a93c429eSMatthew G. Knepley } 10452a93c429eSMatthew G. Knepley } 10453a93c429eSMatthew G. Knepley } 10454a93c429eSMatthew G. Knepley } 10455a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 104569371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 104579371c9d4SSatish Balay bsLocal[1] = bs; 104589566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 104599371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 104609371c9d4SSatish Balay bs = 1; 104619371c9d4SSatish Balay } else { 104629371c9d4SSatish Balay bs = bsMinMax[0]; 104639371c9d4SSatish Balay } 104649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10465a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10466a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10467a93c429eSMatthew G. Knepley 104689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10469a93c429eSMatthew G. Knepley if (gdof > 0) { 10470a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10471a93c429eSMatthew G. Knepley 104729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10473a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10474a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10475a93c429eSMatthew G. Knepley 10476a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10477a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 104789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 104799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10480a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10481a93c429eSMatthew G. Knepley } 104829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 104839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10484ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10485a93c429eSMatthew G. Knepley } 10486a93c429eSMatthew G. Knepley } 10487a93c429eSMatthew G. Knepley } 104889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 104899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10490a93c429eSMatthew G. Knepley if (bs > 1) { 10491a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10492a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10493a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10494a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 104959371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 104969371c9d4SSatish Balay set = 0; 104979371c9d4SSatish Balay break; 104989371c9d4SSatish Balay } 10499a93c429eSMatthew G. Knepley } 10500a93c429eSMatthew G. Knepley } 105019566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10502a93c429eSMatthew G. Knepley } 10503a93c429eSMatthew G. Knepley /* Attach nullspace */ 10504a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10505a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10506a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10507a93c429eSMatthew G. Knepley } 10508a93c429eSMatthew G. Knepley if (f < Nf) { 10509a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 105109566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 105116823f3c5SBlaise Bourdin 105129566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 105139566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10514a93c429eSMatthew G. Knepley } 10515a93c429eSMatthew G. Knepley } 105163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10517a93c429eSMatthew G. Knepley } 10518c0f0dcc3SMatthew G. Knepley 10519c0f0dcc3SMatthew G. Knepley /*@ 10520c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10521c0f0dcc3SMatthew G. Knepley 10522a1cb98faSBarry Smith Input Parameters: 10523a1cb98faSBarry Smith + dm - The `DM` 10524a1cb98faSBarry Smith - dummy - unused argument 10525a1cb98faSBarry Smith 10526a1cb98faSBarry Smith Options Database Key: 10527a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10528c0f0dcc3SMatthew G. Knepley 10529c0f0dcc3SMatthew G. Knepley Level: developer 10530c0f0dcc3SMatthew G. Knepley 105311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10532c0f0dcc3SMatthew G. Knepley @*/ 10533d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10534d71ae5a4SJacob Faibussowitsch { 10535b665b14eSToby Isaac PetscLogHandler default_handler; 10536b665b14eSToby Isaac 105372611ad71SToby Isaac PetscFunctionBegin; 105382611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10539b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10540b665b14eSToby Isaac if (default_handler) { 10541c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10542c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10543c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10544c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10545c0f0dcc3SMatthew G. Knepley const char *name; 10546c0f0dcc3SMatthew G. Knepley 105479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 105489566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 105499566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 105509566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10551b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10552c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10553c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10554c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1055563a3b9bcSJacob 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))); 105562611ad71SToby Isaac } else { 10557b665b14eSToby 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."); 105582611ad71SToby Isaac } 105593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10560c0f0dcc3SMatthew G. Knepley } 10561