1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11552f7358SJed Brown 12552f7358SJed Brown /* Logging support */ 1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad; 14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 15552f7358SJed Brown 16f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 18f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 19f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 20f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 21f39ec787SMatthew G. Knepley "volume = {38},\n" 22f39ec787SMatthew G. Knepley "number = {5},\n" 23f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 24f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 25f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 26f39ec787SMatthew G. Knepley "year = {2016},\n" 27f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 28f39ec787SMatthew G. Knepley 295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 30552f7358SJed Brown 31e5337592SStefano Zampini /*@ 329318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 339318fe57SMatthew G. Knepley 349318fe57SMatthew G. Knepley Input Parameter: 35a1cb98faSBarry Smith . dm - The `DMPLEX` object 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley Output Parameter: 389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley Level: intermediate 419318fe57SMatthew G. Knepley 42a1cb98faSBarry Smith Note: 43a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 44a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 45a1cb98faSBarry Smith 461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 479318fe57SMatthew G. Knepley @*/ 48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 49d71ae5a4SJacob Faibussowitsch { 509318fe57SMatthew G. Knepley DMPolytopeType ct; 519318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 529318fe57SMatthew G. Knepley 539318fe57SMatthew G. Knepley PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 559371c9d4SSatish Balay if (cEnd <= cStart) { 569371c9d4SSatish Balay *simplex = PETSC_FALSE; 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589371c9d4SSatish Balay } 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 609318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629318fe57SMatthew G. Knepley } 639318fe57SMatthew G. Knepley 649318fe57SMatthew G. Knepley /*@ 65412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 66e5337592SStefano Zampini 67d8d19677SJose E. Roman Input Parameters: 68a1cb98faSBarry Smith + dm - The `DMPLEX` object 69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 70e5337592SStefano Zampini 71e5337592SStefano Zampini Output Parameters: 72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7340196513SBarry Smith - cEnd - The upper bound on "normal" cells 74e5337592SStefano Zampini 75412e9a14SMatthew G. Knepley Level: developer 76e5337592SStefano Zampini 77a1cb98faSBarry Smith Note: 785ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 79a1cb98faSBarry Smith 802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 81e5337592SStefano Zampini @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 83d71ae5a4SJacob Faibussowitsch { 845ae96e2bSMatthew G. Knepley DMLabel ctLabel; 855ae96e2bSMatthew G. Knepley IS valueIS; 865ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 875ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 88e5337592SStefano Zampini 89e5337592SStefano Zampini PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 915ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 925ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 935ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 945ae96e2bSMatthew G. Knepley if (!Nct) cS = cE = 0; 955ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 96c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 975ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 985ae96e2bSMatthew G. Knepley 995ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1005ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1015ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1025ae96e2bSMatthew G. Knepley break; 1035ae96e2bSMatthew G. Knepley } 104c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1055ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1065ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1075ae96e2bSMatthew G. Knepley // Check that a point has the right height 1085ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1095ae96e2bSMatthew G. Knepley if (ht != height) continue; 1105ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1115ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1125ae96e2bSMatthew G. Knepley } 1135ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 114695799ffSMatthew G. Knepley // Reset label for fast lookup 115695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 116412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 117412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119e5337592SStefano Zampini } 120e5337592SStefano Zampini 1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1229c600e38SMatt McGurn { 1239c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1249c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1259c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1269c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1279c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1289c600e38SMatt McGurn 1299c600e38SMatt McGurn PetscFunctionBegin; 1309c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1319c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1329c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1339c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1349c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1359c600e38SMatt McGurn if (field >= 0) { 1369c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1379c600e38SMatt McGurn } else { 1389c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1399c600e38SMatt McGurn } 1409c600e38SMatt McGurn 1419c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1429c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1439c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1449c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1459c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1469c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1479c600e38SMatt McGurn PetscInt dep; 1489c600e38SMatt McGurn 1499c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1509c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1519c600e38SMatt McGurn if (pStart >= 0) { 1529c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1539c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1549c600e38SMatt McGurn } 1559c600e38SMatt McGurn if (field >= 0) { 1569c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1579c600e38SMatt McGurn } else { 1589c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1599c600e38SMatt McGurn } 1609c600e38SMatt McGurn } 1619c600e38SMatt McGurn 1629c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1639c600e38SMatt McGurn *types = 0; 1649c600e38SMatt McGurn 1659c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1669c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1679c600e38SMatt McGurn } 1689c600e38SMatt McGurn 1699c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1709c600e38SMatt McGurn t = 0; 1719c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1729c600e38SMatt McGurn sStart[t] = vStart; 1739c600e38SMatt McGurn sEnd[t] = vEnd; 1749c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1759c600e38SMatt McGurn ++t; 1769c600e38SMatt McGurn } 1779c600e38SMatt McGurn 1789c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1799c600e38SMatt McGurn if (globalvcdof[c]) { 1809c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1819c600e38SMatt McGurn 1829c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1839c600e38SMatt McGurn sStart[t] = cStart; 1849c600e38SMatt McGurn sEnd[t] = cEnd; 1859c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1869c600e38SMatt McGurn ++t; 1879c600e38SMatt McGurn } 1889c600e38SMatt McGurn } 1899c600e38SMatt McGurn 1904ad8454bSPierre Jolivet if (!*types) { 1919c600e38SMatt McGurn if (field >= 0) { 1929c600e38SMatt McGurn const char *fieldname; 1939c600e38SMatt McGurn 1949c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1959c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1969c600e38SMatt McGurn } else { 1979c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 1989c600e38SMatt McGurn } 1999c600e38SMatt McGurn } 2009c600e38SMatt McGurn 2019c600e38SMatt McGurn *ssStart = sStart; 2029c600e38SMatt McGurn *ssEnd = sEnd; 2039c600e38SMatt McGurn *sft = ft; 2049c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2059c600e38SMatt McGurn } 2069c600e38SMatt McGurn 2079c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2089c600e38SMatt McGurn { 2099c600e38SMatt McGurn PetscFunctionBegin; 2109c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2119c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2129c600e38SMatt McGurn } 2139c600e38SMatt McGurn 214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 215d71ae5a4SJacob Faibussowitsch { 216412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 217a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2187e42fee7SMatthew G. Knepley 2197e42fee7SMatthew G. Knepley PetscFunctionBegin; 220e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2257e42fee7SMatthew G. Knepley if (field >= 0) { 2269566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2279566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2287e42fee7SMatthew G. Knepley } else { 2299566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2309566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2317e42fee7SMatthew G. Knepley } 232712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 233a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2347e42fee7SMatthew G. Knepley *sStart = vStart; 2357e42fee7SMatthew G. Knepley *sEnd = vEnd; 236f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2377e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 238a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2397e42fee7SMatthew G. Knepley *sStart = cStart; 2407e42fee7SMatthew G. Knepley *sEnd = cEnd; 241f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2427e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 243e630c359SToby Isaac } else { 244e630c359SToby Isaac if (field >= 0) { 245e630c359SToby Isaac const char *fieldname; 246e630c359SToby Isaac 2479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 24863a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 249e630c359SToby Isaac } else { 25063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 251e630c359SToby Isaac } 252e630c359SToby Isaac } 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2547e42fee7SMatthew G. Knepley } 2557e42fee7SMatthew G. Knepley 2566913077dSMatthew G. Knepley /*@ 2576913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2586913077dSMatthew G. Knepley 25920f4b53cSBarry Smith Collective 2606913077dSMatthew G. Knepley 2616913077dSMatthew G. Knepley Input Parameters: 262a1cb98faSBarry Smith + dm - The `DMPLEX` object 2636913077dSMatthew G. Knepley . n - The number of vectors 2646913077dSMatthew G. Knepley . u - The array of local vectors 265a1cb98faSBarry Smith - viewer - The `PetscViewer` 2666913077dSMatthew G. Knepley 2676913077dSMatthew G. Knepley Level: advanced 2686913077dSMatthew G. Knepley 2691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2706913077dSMatthew G. Knepley @*/ 271d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 272d71ae5a4SJacob Faibussowitsch { 2736913077dSMatthew G. Knepley PetscDS ds; 2746913077dSMatthew G. Knepley PetscDraw draw = NULL; 2756913077dSMatthew G. Knepley PetscDrawLG lg; 2766913077dSMatthew G. Knepley Vec coordinates; 2776913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2786913077dSMatthew G. Knepley PetscReal *vals; 2796913077dSMatthew G. Knepley PetscInt *Nc; 2806913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2816913077dSMatthew G. Knepley char **names; 2826913077dSMatthew G. Knepley 2836913077dSMatthew G. Knepley PetscFunctionBegin; 2849566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2869566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2886913077dSMatthew G. Knepley 2899566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2903ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2919566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2926913077dSMatthew G. Knepley 2939566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2946913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2956913077dSMatthew G. Knepley const char *vname; 2966913077dSMatthew G. Knepley 2979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 2986913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 2996913077dSMatthew G. Knepley PetscObject disc; 3006913077dSMatthew G. Knepley const char *fname; 3016913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3026913077dSMatthew G. Knepley 3039566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3046913077dSMatthew G. Knepley /* TODO Create names for components */ 3056913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 307c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 308c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 309c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3109566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3116913077dSMatthew G. Knepley } 3126913077dSMatthew G. Knepley } 3136913077dSMatthew G. Knepley } 3149566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3156913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3199566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3206913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3216913077dSMatthew G. Knepley PetscScalar *x, *svals; 3226913077dSMatthew G. Knepley 3239566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3246913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3259566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3266913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3276913077dSMatthew G. Knepley } 3289566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3296913077dSMatthew G. Knepley } 3309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3319566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3329566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3339566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3346913077dSMatthew G. Knepley 3359566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3369566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3386913077dSMatthew G. Knepley } 3396913077dSMatthew G. Knepley 340d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 341d71ae5a4SJacob Faibussowitsch { 3426913077dSMatthew G. Knepley DM dm; 3436913077dSMatthew G. Knepley 3446913077dSMatthew G. Knepley PetscFunctionBegin; 3459566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3469566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3486913077dSMatthew G. Knepley } 3496913077dSMatthew G. Knepley 350d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 351d71ae5a4SJacob Faibussowitsch { 352e412dcbdSMatthew G. Knepley DM dm; 353d1df6f1dSMatthew G. Knepley PetscSection s; 354e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 355e412dcbdSMatthew G. Knepley DM cdm; 356e412dcbdSMatthew G. Knepley PetscSection coordSection; 357e412dcbdSMatthew G. Knepley Vec coordinates; 358c9c77995SMatthew G. Knepley const PetscScalar *array; 359c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 360339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3616913077dSMatthew G. Knepley PetscBool flg; 362d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 363e412dcbdSMatthew G. Knepley const char *name; 364339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 365e412dcbdSMatthew G. Knepley 366e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3679566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3689566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3729566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3779566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 378e412dcbdSMatthew G. Knepley 3799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3809566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 381e412dcbdSMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 383c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3849566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 385e412dcbdSMatthew G. Knepley 386d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 387d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 388d1df6f1dSMatthew G. Knepley DM fdm = dm; 389d1df6f1dSMatthew G. Knepley Vec fv = v; 390d1df6f1dSMatthew G. Knepley IS fis; 391d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 392d1df6f1dSMatthew G. Knepley const char *fname; 393d1df6f1dSMatthew G. Knepley 3949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 396d1df6f1dSMatthew G. Knepley 3979566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 398ad540459SPierre Jolivet else prefix[0] = '\0'; 399d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4009566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4019566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4029566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4039566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 404d1df6f1dSMatthew G. Knepley } 405d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 406d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 407d1df6f1dSMatthew G. Knepley 4089566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 40963a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41063a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4119566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 412d1df6f1dSMatthew G. Knepley 413d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 415339e3443SMatthew G. Knepley if (!flg) { 4169566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4179566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 418d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 419339e3443SMatthew G. Knepley } 420c9c77995SMatthew G. Knepley 4219566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4229566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 423c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4249566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 425e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 42699a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 427c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 428c9c77995SMatthew G. Knepley PetscBool isDG; 429e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 430e412dcbdSMatthew G. Knepley 4319566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 432339e3443SMatthew G. Knepley if (a) { 433d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 434339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 435339e3443SMatthew G. Knepley } else { 436339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 437339e3443SMatthew G. Knepley PetscInt numVals, va; 438339e3443SMatthew G. Knepley 4399566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 44063a3b9bcSJacob Faibussowitsch PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals); 441d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 442d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 443d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 444d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 445339e3443SMatthew G. Knepley break; 446d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 447d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 448d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / (Nc * 2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp + numVals / (Nc * 2)]), vbound[0], vbound[1]); 449d1df6f1dSMatthew G. Knepley break; 450d71ae5a4SJacob Faibussowitsch default: 451d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 452339e3443SMatthew G. Knepley } 4539566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 454339e3443SMatthew G. Knepley } 455c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 456e412dcbdSMatthew G. Knepley switch (numCoords) { 457e412dcbdSMatthew G. Knepley case 6: 4589edc3542SMatthew Knepley case 12: /* Localized triangle */ 4599566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 460e412dcbdSMatthew G. Knepley break; 461e412dcbdSMatthew G. Knepley case 8: 4629edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 4639566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 4649566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0])); 465e412dcbdSMatthew G. Knepley break; 466d71ae5a4SJacob Faibussowitsch default: 467d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 468e412dcbdSMatthew G. Knepley } 469c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 470e412dcbdSMatthew G. Knepley } 4719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4729566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4739566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 475d1df6f1dSMatthew G. Knepley } 476d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4779566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4799566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 480d1df6f1dSMatthew G. Knepley } 481d1df6f1dSMatthew G. Knepley } 4823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 483e412dcbdSMatthew G. Knepley } 484e412dcbdSMatthew G. Knepley 485d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 486d71ae5a4SJacob Faibussowitsch { 4876913077dSMatthew G. Knepley DM dm; 4886913077dSMatthew G. Knepley PetscDraw draw; 4896913077dSMatthew G. Knepley PetscInt dim; 4906913077dSMatthew G. Knepley PetscBool isnull; 4916913077dSMatthew G. Knepley 4926913077dSMatthew G. Knepley PetscFunctionBegin; 4939566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4953ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4966913077dSMatthew G. Knepley 4979566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 4989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 4996913077dSMatthew G. Knepley switch (dim) { 500d71ae5a4SJacob Faibussowitsch case 1: 501d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 502d71ae5a4SJacob Faibussowitsch break; 503d71ae5a4SJacob Faibussowitsch case 2: 504d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 505d71ae5a4SJacob Faibussowitsch break; 506d71ae5a4SJacob Faibussowitsch default: 507d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5086913077dSMatthew G. Knepley } 5093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5106913077dSMatthew G. Knepley } 5116913077dSMatthew G. Knepley 512d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 513d71ae5a4SJacob Faibussowitsch { 514684b87d9SLisandro Dalcin DM dm; 515684b87d9SLisandro Dalcin Vec locv; 516684b87d9SLisandro Dalcin const char *name; 517684b87d9SLisandro Dalcin PetscSection section; 518684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 519e630c359SToby Isaac PetscInt numFields; 520684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 521684b87d9SLisandro Dalcin 522684b87d9SLisandro Dalcin PetscFunctionBegin; 5239566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5249566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5279566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5289566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 530e630c359SToby Isaac if (!numFields) { 5319566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5329566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 533e630c359SToby Isaac } else { 534e630c359SToby Isaac PetscInt f; 535e630c359SToby Isaac 536e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5379566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 538e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5409566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 541e630c359SToby Isaac } 5429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 543e630c359SToby Isaac } 5443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 545684b87d9SLisandro Dalcin } 546684b87d9SLisandro Dalcin 547d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 548d71ae5a4SJacob Faibussowitsch { 549552f7358SJed Brown DM dm; 5505f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 551552f7358SJed Brown 552552f7358SJed Brown PetscFunctionBegin; 5539566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 55428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5595f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5605f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 561684b87d9SLisandro Dalcin PetscInt i, numFields; 562684b87d9SLisandro Dalcin PetscObject fe; 563ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 564684b87d9SLisandro Dalcin Vec locv = v; 565684b87d9SLisandro Dalcin const char *name; 566684b87d9SLisandro Dalcin PetscInt step; 567684b87d9SLisandro Dalcin PetscReal time; 568ef31f671SMatthew G. Knepley 5699566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 570684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5719566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5729371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5739371c9d4SSatish Balay fem = PETSC_TRUE; 5749371c9d4SSatish Balay break; 5759371c9d4SSatish Balay } 576ef31f671SMatthew G. Knepley } 577684b87d9SLisandro Dalcin if (fem) { 578798534f6SMatthew G. Knepley PetscObject isZero; 579798534f6SMatthew G. Knepley 5809566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5859566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5869566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 5879566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 588ef31f671SMatthew G. Knepley } 589552f7358SJed Brown if (isvtk) { 5909566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 591b136c2c9SMatthew G. Knepley } else if (ishdf5) { 592b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5939566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 594b136c2c9SMatthew G. Knepley #else 595b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 596b136c2c9SMatthew G. Knepley #endif 597f13a32a3SMatthew G. Knepley } else if (isdraw) { 5989566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 599684b87d9SLisandro Dalcin } else if (isglvis) { 6009566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6019566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6029566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6035f34f2dcSJed Brown } else if (iscgns) { 6045f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6055f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6065f34f2dcSJed Brown #else 6075f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6085f34f2dcSJed Brown #endif 609684b87d9SLisandro Dalcin } 610798534f6SMatthew G. Knepley if (fem) { 6119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6129566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 613798534f6SMatthew G. Knepley } 614552f7358SJed Brown } else { 615684b87d9SLisandro Dalcin PetscBool isseq; 616684b87d9SLisandro Dalcin 6179566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6189566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6199566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 620552f7358SJed Brown } 6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 622552f7358SJed Brown } 623552f7358SJed Brown 624d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 625d71ae5a4SJacob Faibussowitsch { 626552f7358SJed Brown DM dm; 6275f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 628552f7358SJed Brown 629552f7358SJed Brown PetscFunctionBegin; 6309566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63128b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6365f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6385f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 639552f7358SJed Brown Vec locv; 640798534f6SMatthew G. Knepley PetscObject isZero; 641552f7358SJed Brown const char *name; 642552f7358SJed Brown 6439566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6469566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6489566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6499566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6509566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6529566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 653b136c2c9SMatthew G. Knepley } else if (ishdf5) { 654b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6559566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 656b136c2c9SMatthew G. Knepley #else 657b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 658b136c2c9SMatthew G. Knepley #endif 6596823f3c5SBlaise Bourdin } else if (isexodusii) { 6606823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6619566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6626823f3c5SBlaise Bourdin #else 6636823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6646823f3c5SBlaise Bourdin #endif 665552f7358SJed Brown } else { 666684b87d9SLisandro Dalcin PetscBool isseq; 667684b87d9SLisandro Dalcin 6689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6699566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6709566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 671552f7358SJed Brown } 6723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 673552f7358SJed Brown } 674552f7358SJed Brown 675d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 676d71ae5a4SJacob Faibussowitsch { 677d930f514SMatthew G. Knepley DM dm; 678d930f514SMatthew G. Knepley MPI_Comm comm; 679d930f514SMatthew G. Knepley PetscViewerFormat format; 680d930f514SMatthew G. Knepley Vec v; 681d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 682d930f514SMatthew G. Knepley 683d930f514SMatthew G. Knepley PetscFunctionBegin; 6849566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 6859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 68628b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6879566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 690d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 691a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 692a8ad634aSStefano Zampini /* this need a better fix */ 693a8ad634aSStefano Zampini if (dm->useNatural) { 694a8ad634aSStefano Zampini if (dm->sfNatural) { 695d930f514SMatthew G. Knepley const char *vecname; 696d930f514SMatthew G. Knepley PetscInt n, nroots; 697d930f514SMatthew G. Knepley 6989566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 6999566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 700d930f514SMatthew G. Knepley if (n == nroots) { 701f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7029566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7039566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 706d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 707d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 708a8ad634aSStefano Zampini } else v = originalv; 709a8ad634aSStefano Zampini } else v = originalv; 710a8ad634aSStefano Zampini 711d930f514SMatthew G. Knepley if (ishdf5) { 712d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7139566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 714d930f514SMatthew G. Knepley #else 715d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 716d930f514SMatthew G. Knepley #endif 717d930f514SMatthew G. Knepley } else if (isvtk) { 718d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 719d930f514SMatthew G. Knepley } else { 720d930f514SMatthew G. Knepley PetscBool isseq; 721d930f514SMatthew G. Knepley 7229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7239566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7249566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 725d930f514SMatthew G. Knepley } 726f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 728d930f514SMatthew G. Knepley } 729d930f514SMatthew G. Knepley 730d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 731d71ae5a4SJacob Faibussowitsch { 7322c40f234SMatthew G. Knepley DM dm; 7332c40f234SMatthew G. Knepley PetscBool ishdf5; 7342c40f234SMatthew G. Knepley 7352c40f234SMatthew G. Knepley PetscFunctionBegin; 7369566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 73728b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7392c40f234SMatthew G. Knepley if (ishdf5) { 7402c40f234SMatthew G. Knepley DM dmBC; 7412c40f234SMatthew G. Knepley Vec gv; 7422c40f234SMatthew G. Knepley const char *name; 7432c40f234SMatthew G. Knepley 7449566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7459566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7489566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7509566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7519566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7521baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7542c40f234SMatthew G. Knepley } 7552c40f234SMatthew G. Knepley 756d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 757d71ae5a4SJacob Faibussowitsch { 7582c40f234SMatthew G. Knepley DM dm; 7596823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7602c40f234SMatthew G. Knepley 7612c40f234SMatthew G. Knepley PetscFunctionBegin; 7629566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7662c40f234SMatthew G. Knepley if (ishdf5) { 767878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7689566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 769b136c2c9SMatthew G. Knepley #else 770b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 771878b459fSMatthew G. Knepley #endif 7726823f3c5SBlaise Bourdin } else if (isexodusii) { 7736823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7749566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7756823f3c5SBlaise Bourdin #else 7766823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7776823f3c5SBlaise Bourdin #endif 7781baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 780552f7358SJed Brown } 781552f7358SJed Brown 782d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 783d71ae5a4SJacob Faibussowitsch { 784d930f514SMatthew G. Knepley DM dm; 785d930f514SMatthew G. Knepley PetscViewerFormat format; 786d930f514SMatthew G. Knepley PetscBool ishdf5; 787d930f514SMatthew G. Knepley 788d930f514SMatthew G. Knepley PetscFunctionBegin; 7899566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 79028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 793d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 794a8ad634aSStefano Zampini if (dm->useNatural) { 795d930f514SMatthew G. Knepley if (dm->sfNatural) { 796d930f514SMatthew G. Knepley if (ishdf5) { 797d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 798d930f514SMatthew G. Knepley Vec v; 799d930f514SMatthew G. Knepley const char *vecname; 800d930f514SMatthew G. Knepley 801f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8049566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8059566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8069566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 807f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 808d930f514SMatthew G. Knepley #else 809d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 810d930f514SMatthew G. Knepley #endif 811d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 812d930f514SMatthew G. Knepley } 8131baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 814d930f514SMatthew G. Knepley } 8153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 816d930f514SMatthew G. Knepley } 817d930f514SMatthew G. Knepley 818d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 819d71ae5a4SJacob Faibussowitsch { 820731e8ddeSMatthew G. Knepley PetscSection coordSection; 821731e8ddeSMatthew G. Knepley Vec coordinates; 822ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 823731e8ddeSMatthew G. Knepley const char *name[4]; 824731e8ddeSMatthew G. Knepley const PetscScalar *a; 825731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 826731e8ddeSMatthew G. Knepley 827731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8359566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 836731e8ddeSMatthew G. Knepley name[0] = "vertex"; 837731e8ddeSMatthew G. Knepley name[1] = "edge"; 838731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 839731e8ddeSMatthew G. Knepley name[dim] = "cell"; 840731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 841731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 842ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 843731e8ddeSMatthew G. Knepley 8449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 84563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 848731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 849731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 850731e8ddeSMatthew G. Knepley 851731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 853731e8ddeSMatthew G. Knepley if (!dof) continue; 8549566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 85663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 857731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 859731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8609566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 862731e8ddeSMatthew G. Knepley } 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 864731e8ddeSMatthew G. Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 866731e8ddeSMatthew G. Knepley } 8679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 869731e8ddeSMatthew G. Knepley } 8709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 872731e8ddeSMatthew G. Knepley } 873731e8ddeSMatthew G. Knepley 8749371c9d4SSatish Balay typedef enum { 8759371c9d4SSatish Balay CS_CARTESIAN, 8769371c9d4SSatish Balay CS_POLAR, 8779371c9d4SSatish Balay CS_CYLINDRICAL, 8789371c9d4SSatish Balay CS_SPHERICAL 8799371c9d4SSatish Balay } CoordSystem; 88019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 88119ad8254SMatthew G. Knepley 882d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 883d71ae5a4SJacob Faibussowitsch { 88419ad8254SMatthew G. Knepley PetscInt i; 88519ad8254SMatthew G. Knepley 88619ad8254SMatthew G. Knepley PetscFunctionBegin; 88719ad8254SMatthew G. Knepley if (dim > 3) { 8889566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 88919ad8254SMatthew G. Knepley } else { 890bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 89119ad8254SMatthew G. Knepley 89219ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 89319ad8254SMatthew G. Knepley switch (cs) { 8949371c9d4SSatish Balay case CS_CARTESIAN: 8959371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8969371c9d4SSatish Balay break; 89719ad8254SMatthew G. Knepley case CS_POLAR: 89863a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 89919ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90019ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90119ad8254SMatthew G. Knepley break; 90219ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 90363a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 90419ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90519ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90619ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 90719ad8254SMatthew G. Knepley break; 90819ad8254SMatthew G. Knepley case CS_SPHERICAL: 90963a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 91019ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 91119ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 91219ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 91319ad8254SMatthew G. Knepley break; 91419ad8254SMatthew G. Knepley } 9159566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 91619ad8254SMatthew G. Knepley } 9173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91819ad8254SMatthew G. Knepley } 91919ad8254SMatthew G. Knepley 920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 921d71ae5a4SJacob Faibussowitsch { 922552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9236858538eSMatthew G. Knepley DM cdm, cdmCell; 9246858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9256858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 926552f7358SJed Brown PetscViewerFormat format; 927552f7358SJed Brown 928552f7358SJed Brown PetscFunctionBegin; 9299566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 930552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 931552f7358SJed Brown const char *name; 932f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9339318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 934552f7358SJed Brown PetscMPIInt rank, size; 935552f7358SJed Brown 9369f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9379f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9389f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9399f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9409f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9419f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9459566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9469566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9489566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94963a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 95063a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 95163a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 95263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 95463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 955552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 956552f7358SJed Brown PetscInt dof, off, s; 957552f7358SJed Brown 9589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 96048a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 961552f7358SJed Brown } 9629566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 96363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 96463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 965552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 966552f7358SJed Brown PetscInt dof, off, c; 967552f7358SJed Brown 9689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 97048a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 971552f7358SJed Brown } 9729566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9743d2e540fSStefano Zampini if (coordSection && coordinates) { 97519ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9766858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 9776858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 97819ad8254SMatthew G. Knepley PetscMPIInt rank; 97919ad8254SMatthew G. Knepley const char *name; 98019ad8254SMatthew G. Knepley 9819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 9829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 9839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 98463a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 9859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 9866858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 9876858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 9886858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 9896858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 9909566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 99163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 99263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9939566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 99419ad8254SMatthew G. Knepley 9959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9966858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 9989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 99919ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 100019ad8254SMatthew G. Knepley PetscInt dof, off; 100119ad8254SMatthew G. Knepley 10026858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10056858538eSMatthew G. Knepley if (dof) { 100663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10079566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 100919ad8254SMatthew G. Knepley } 10106858538eSMatthew G. Knepley } 10116858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10126858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10136858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10146858538eSMatthew G. Knepley if (dof) { 10156858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10166858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10176858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10186858538eSMatthew G. Knepley } 10196858538eSMatthew G. Knepley } 10206858538eSMatthew G. Knepley } 10219566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10246858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10253d2e540fSStefano Zampini } 10269566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10279566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10289318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10299318fe57SMatthew G. Knepley DMLabel label; 10309318fe57SMatthew G. Knepley PetscBool isdepth; 10319318fe57SMatthew G. Knepley const char *name; 10329318fe57SMatthew G. Knepley 10339566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10359318fe57SMatthew G. Knepley if (isdepth) continue; 10369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10379566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10389318fe57SMatthew G. Knepley } 1039552f7358SJed Brown if (size > 1) { 1040552f7358SJed Brown PetscSF sf; 1041552f7358SJed Brown 10429566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1044552f7358SJed Brown } 10454e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 10469566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1047552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10480588280cSMatthew G. Knepley const char *name, *color; 10490588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10500588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1051fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1052552f7358SJed Brown PetscReal scale = 2.0; 105378081901SStefano Zampini PetscReal tikzscale = 1.0; 1054b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10550588280cSMatthew G. Knepley double tcoords[3]; 1056552f7358SJed Brown PetscScalar *coords; 1057b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 1058552f7358SJed Brown PetscMPIInt rank, size; 10590588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1060b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1061fe1cc32dSStefano Zampini PetscBT wp = NULL; 1062fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1063552f7358SJed Brown 10649f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10659f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10669f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10679f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10689f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10699f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10729566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10730588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10740588280cSMatthew G. Knepley numColors = 10; 10750588280cSMatthew G. Knepley numLColors = 10; 10769566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 10779566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 10789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 10799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1080b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1081b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1082b7f6ffafSMatthew G. Knepley n = 4; 10839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 10841dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 1085bd3611e6SMatthew G. Knepley n = 4; 10869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10871dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 10889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10890588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10910588280cSMatthew G. Knepley if (!useColors) { 10920588280cSMatthew G. Knepley numColors = 3; 10939566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10940588280cSMatthew G. Knepley } 10959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10960588280cSMatthew G. Knepley if (!useColors) { 10970588280cSMatthew G. Knepley numLColors = 4; 10989566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 10990588280cSMatthew G. Knepley } 11009566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1101b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11031dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1104202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1106fe1cc32dSStefano Zampini 1107fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11099566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1112fe1cc32dSStefano Zampini if (lflg) { 1113fe1cc32dSStefano Zampini DMLabel lbl; 1114fe1cc32dSStefano Zampini 11159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1116fe1cc32dSStefano Zampini if (lbl) { 1117fe1cc32dSStefano Zampini PetscInt val, defval; 1118fe1cc32dSStefano Zampini 11199566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11209566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1121fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1122fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1123fe1cc32dSStefano Zampini PetscInt closureSize; 1124fe1cc32dSStefano Zampini 11259566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1126fe1cc32dSStefano Zampini if (val == defval) continue; 1127fe1cc32dSStefano Zampini 11289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 112948a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1131fe1cc32dSStefano Zampini } 1132fe1cc32dSStefano Zampini } 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini 11359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11390588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1140552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1141552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1142552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11435f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11440588280cSMatthew G. Knepley if (size > 1) { 11459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1146770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114763a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 114863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1149770b213bSMatthew G Knepley } 11509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11510588280cSMatthew G. Knepley } 1152b7f6ffafSMatthew G. Knepley if (drawHasse) { 1153b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1154b7f6ffafSMatthew G. Knepley 115563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 115963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1167b7f6ffafSMatthew G. Knepley } 11689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1169fe1cc32dSStefano Zampini 1170552f7358SJed Brown /* Plot vertices */ 11719566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1173552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1174552f7358SJed Brown PetscInt off, dof, d; 11750588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1176552f7358SJed Brown 1177fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118163a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11820588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11830588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1184c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11850588280cSMatthew G. Knepley } 11860588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11879371c9d4SSatish Balay if (dim == 3) { 11889371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11899371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11909371c9d4SSatish Balay tcoords[2] = -tmp; 11919371c9d4SSatish Balay } 1192552f7358SJed Brown for (d = 0; d < dof; ++d) { 11939566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1195552f7358SJed Brown } 1196b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1197b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 11980588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 11990588280cSMatthew G. Knepley PetscInt val; 12009566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12019371c9d4SSatish Balay if (val >= 0) { 12029371c9d4SSatish Balay color = lcolors[l % numLColors]; 12039371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12049371c9d4SSatish Balay break; 12059371c9d4SSatish Balay } 12060588280cSMatthew G. Knepley } 1207b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 120863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1209b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12111baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1212552f7358SJed Brown } 12139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1215b7f6ffafSMatthew G. Knepley /* Plot edges */ 1216b7f6ffafSMatthew G. Knepley if (plotEdges) { 12179566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1219b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1220b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1221b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1222b7f6ffafSMatthew G. Knepley 1223b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122563a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1231b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1232b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1233b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1234b7f6ffafSMatthew G. Knepley } 1235b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12369371c9d4SSatish Balay if (dim == 3) { 12379371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12389371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12399371c9d4SSatish Balay tcoords[2] = -tmp; 12409371c9d4SSatish Balay } 1241b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12429566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1244b7f6ffafSMatthew G. Knepley } 1245b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1246b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1247b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1248b7f6ffafSMatthew G. Knepley PetscInt val; 1249bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12509371c9d4SSatish Balay if (val >= 0) { 12519371c9d4SSatish Balay color = lcolors[l % numLColors]; 12529371c9d4SSatish Balay break; 12539371c9d4SSatish Balay } 1254b7f6ffafSMatthew G. Knepley } 125563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1256b7f6ffafSMatthew G. Knepley } 12579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12589566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1260b7f6ffafSMatthew G. Knepley } 1261846a3e8bSMatthew G. Knepley /* Plot cells */ 1262b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1263846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1264846a3e8bSMatthew G. Knepley const PetscInt *cone; 1265846a3e8bSMatthew G. Knepley 1266fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1267846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1268846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1269846a3e8bSMatthew G. Knepley PetscInt val; 12709566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12719371c9d4SSatish Balay if (val >= 0) { 12729371c9d4SSatish Balay color = lcolors[l % numLColors]; 12739371c9d4SSatish Balay break; 12749371c9d4SSatish Balay } 1275846a3e8bSMatthew G. Knepley } 12769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1278846a3e8bSMatthew G. Knepley } 1279846a3e8bSMatthew G. Knepley } else { 1280b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1281846a3e8bSMatthew G. Knepley 1282b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1283b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1284fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12859566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1286c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1287b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1288b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1289b7f6ffafSMatthew G. Knepley 12909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1292b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1293b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1294b7f6ffafSMatthew G. Knepley 12959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1297b7f6ffafSMatthew G. Knepley } 1298b7f6ffafSMatthew G. Knepley } else { 1299b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1300b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1301b7f6ffafSMatthew G. Knepley 13029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1303846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1304846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1305846a3e8bSMatthew G. Knepley 1306b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1307846a3e8bSMatthew G. Knepley } 13089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1309b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1310b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1311b7f6ffafSMatthew G. Knepley 1312b7f6ffafSMatthew G. Knepley if (v > 0) { 1313b7f6ffafSMatthew G. Knepley if (plotEdges) { 1314b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1315b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1316b7f6ffafSMatthew G. Knepley 13179371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13189371c9d4SSatish Balay endpoints[1] = vertex; 13199566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132063a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13229566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13231baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1324b7f6ffafSMatthew G. Knepley } 132563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1326b7f6ffafSMatthew G. Knepley } 13279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1329846a3e8bSMatthew G. Knepley } 1330846a3e8bSMatthew G. Knepley } 1331b7f6ffafSMatthew G. Knepley } 1332846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1333846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1334846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1335c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1336c713ec31SMatthew G. Knepley const PetscScalar *array; 1337c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1338c713ec31SMatthew G. Knepley PetscBool isDG; 1339846a3e8bSMatthew G. Knepley 1340fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1341c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1342c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1343c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1345c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1346c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1347c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1348846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1349846a3e8bSMatthew G. Knepley } 1350846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13519371c9d4SSatish Balay if (cdim == 3) { 13529371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13539371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13549371c9d4SSatish Balay tcoords[2] = -tmp; 13559371c9d4SSatish Balay } 1356ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1357846a3e8bSMatthew G. Knepley } 1358ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1359c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1360c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13619566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1363846a3e8bSMatthew G. Knepley } 1364b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1365b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1366846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1367846a3e8bSMatthew G. Knepley PetscInt val; 13689566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13699371c9d4SSatish Balay if (val >= 0) { 13709371c9d4SSatish Balay color = lcolors[l % numLColors]; 13719371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13729371c9d4SSatish Balay break; 13739371c9d4SSatish Balay } 1374846a3e8bSMatthew G. Knepley } 1375b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1377b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 137863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13791baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1380846a3e8bSMatthew G. Knepley } 1381b7f6ffafSMatthew G. Knepley if (drawHasse) { 1382b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1388552f7358SJed Brown 1389b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1395b7f6ffafSMatthew G. Knepley 1396b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 13989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1402b7f6ffafSMatthew G. Knepley 1403b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1404b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1405b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1406b7f6ffafSMatthew G. Knepley 14079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14089566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 140948a46eb9SPierre Jolivet for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 14100588280cSMatthew G. Knepley } 14110588280cSMatthew G. Knepley } 14129566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14169566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14179566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14189566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14199566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14209566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14210f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14220f7d6e4aSStefano Zampini Vec cown, acown; 14230f7d6e4aSStefano Zampini VecScatter sct; 14240f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14250f7d6e4aSStefano Zampini IS gid, acis; 14260f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14270f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14280f7d6e4aSStefano Zampini PetscScalar *array, nid; 14290f7d6e4aSStefano Zampini const PetscInt *idxs; 14300f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14310f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14320f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14330f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14340f7d6e4aSStefano Zampini 14359566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1437b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14390f7d6e4aSStefano Zampini #endif 14400f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14430f7d6e4aSStefano Zampini d1 = 0; 14449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14450f7d6e4aSStefano Zampini nid = d2; 14469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14490f7d6e4aSStefano Zampini } else nid = 0.0; 14500f7d6e4aSStefano Zampini 14510f7d6e4aSStefano Zampini /* Get connectivity */ 14529566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14539566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14540f7d6e4aSStefano Zampini 14550f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14600f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14610f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14620f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14630f7d6e4aSStefano Zampini } 14649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146563a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14680f7d6e4aSStefano Zampini 14690f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14719566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14729566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14739566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14740f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14769566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14809566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14820f7d6e4aSStefano Zampini 14830f7d6e4aSStefano Zampini /* compute edgeCut */ 14840f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14899566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14900f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14910f7d6e4aSStefano Zampini PetscInt totl; 14920f7d6e4aSStefano Zampini 14930f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14949566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14950f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14960f7d6e4aSStefano Zampini if (work[i] < 0) { 14970f7d6e4aSStefano Zampini ect += 1; 14980f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 14990f7d6e4aSStefano Zampini } 15000f7d6e4aSStefano Zampini } 15010f7d6e4aSStefano Zampini } 15029566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15040f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15050f7d6e4aSStefano Zampini lm[1] = -numVertices; 15061c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0])); 15080f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15090f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15100f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1513b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1514f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.)); 15150f7d6e4aSStefano Zampini #else 151663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15170f7d6e4aSStefano Zampini #endif 15189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15199566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1522552f7358SJed Brown } else { 1523412e9a14SMatthew G. Knepley const char *name; 1524d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1525412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1526d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1527ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15289318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1529412e9a14SMatthew G. Knepley MPI_Comm comm; 1530412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1531552f7358SJed Brown 15329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15369566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 153863a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 153963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154063a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15421c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15432827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1544d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15459566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15469566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1547412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1548412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1549412e9a14SMatthew G. Knepley 15509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15519566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1552412e9a14SMatthew G. Knepley ict = ct0; 15539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1554412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1555412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1556412e9a14SMatthew G. Knepley DMPolytopeType ct; 1557412e9a14SMatthew G. Knepley 15589566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1559412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1560412e9a14SMatthew G. Knepley else ++Nc[1]; 1561412e9a14SMatthew G. Knepley } 1562ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15659566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1567834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1568dd400576SPatrick Sanan if (rank == 0) { 156963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157063a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157163a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1572834065abSMatthew G. Knepley } 1573cbb7f117SMark Adams } 1574ca7bf7eeSMatthew G. Knepley } else { 1575ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1576ca7bf7eeSMatthew G. Knepley 15779371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15789371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15799566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15809371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15819371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15829566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1583ca7bf7eeSMatthew G. Knepley if (d == depth) { 15849371c9d4SSatish Balay locMinMax[0] = gcNum; 15859371c9d4SSatish Balay locMinMax[1] = gcNum; 15869566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1587ca7bf7eeSMatthew G. Knepley } 158863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15909566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15919566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1592ca7bf7eeSMatthew G. Knepley } 15939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1594552f7358SJed Brown } 15959566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15969318fe57SMatthew G. Knepley { 15979318fe57SMatthew G. Knepley const PetscReal *maxCell; 15989318fe57SMatthew G. Knepley const PetscReal *L; 15996858538eSMatthew G. Knepley PetscBool localized; 16009318fe57SMatthew G. Knepley 16014fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16036858538eSMatthew G. Knepley if (L || localized) { 16046858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16066858538eSMatthew G. Knepley if (L) { 16076858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16089318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16096858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16106858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16119318fe57SMatthew G. Knepley } 16126858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16136858538eSMatthew G. Knepley } 16146858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16169318fe57SMatthew G. Knepley } 16179318fe57SMatthew G. Knepley } 16189566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16199566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1620a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1621a57dd577SMatthew G Knepley DMLabel label; 1622a57dd577SMatthew G Knepley const char *name; 1623a57dd577SMatthew G Knepley IS valueIS; 1624a57dd577SMatthew G Knepley const PetscInt *values; 1625a57dd577SMatthew G Knepley PetscInt numValues, v; 1626a57dd577SMatthew G Knepley 16279566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16289566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16299566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1634a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1635a57dd577SMatthew G Knepley PetscInt size; 1636a57dd577SMatthew G Knepley 16379566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16389566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 163963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1640a57dd577SMatthew G Knepley } 16419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1645a57dd577SMatthew G Knepley } 1646c1cad2e7SMatthew G. Knepley { 1647c1cad2e7SMatthew G. Knepley char **labelNames; 1648c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1649c1cad2e7SMatthew G. Knepley PetscBool flg; 1650c1cad2e7SMatthew G. Knepley 16519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16529566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1653c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1654c1cad2e7SMatthew G. Knepley DMLabel label; 1655c1cad2e7SMatthew G. Knepley 16569566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1657c1cad2e7SMatthew G. Knepley if (flg) { 16589566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16599566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1660c1cad2e7SMatthew G. Knepley } 16619566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1662c1cad2e7SMatthew G. Knepley } 16639566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1664c1cad2e7SMatthew G. Knepley } 166534aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166634aa8a36SMatthew G. Knepley if (dm->Nf) { 166734aa8a36SMatthew G. Knepley PetscInt f; 166834aa8a36SMatthew G. Knepley 166934aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167034aa8a36SMatthew G. Knepley const char *name; 167134aa8a36SMatthew G. Knepley 16729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16739566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16759566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167634aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16779566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16789566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 167934aa8a36SMatthew G. Knepley } else { 16809566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16819566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168234aa8a36SMatthew G. Knepley } 16839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168434aa8a36SMatthew G. Knepley } 168534aa8a36SMatthew G. Knepley } 16869566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16878e7ff633SMatthew G. Knepley if (cdm) { 16889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16899f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16909566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16928e7ff633SMatthew G. Knepley } 1693552f7358SJed Brown } 16943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1695552f7358SJed Brown } 1696552f7358SJed Brown 1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1698d71ae5a4SJacob Faibussowitsch { 1699e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1700e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1701a12d352dSMatthew G. Knepley PetscInt cdim; 1702e5c487bfSMatthew G. Knepley 1703e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1707e5c487bfSMatthew G. Knepley switch (ct) { 1708a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1709a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1710a12d352dSMatthew G. Knepley switch (cdim) { 17119371c9d4SSatish Balay case 1: { 1712a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1713a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1714a12d352dSMatthew G. Knepley 17159566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17169566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17189371c9d4SSatish Balay } break; 17199371c9d4SSatish Balay case 2: { 1720a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1721a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1722a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1723a12d352dSMatthew G. Knepley 17249566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17259566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK)); 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK)); 17279371c9d4SSatish Balay } break; 1728d71ae5a4SJacob Faibussowitsch default: 1729d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1730a12d352dSMatthew G. Knepley } 1731a12d352dSMatthew G. Knepley break; 1732e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17339371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17349566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17359566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1737e5c487bfSMatthew G. Knepley break; 1738e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17399371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17409371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17419566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17429566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1745e5c487bfSMatthew G. Knepley break; 17469f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17479f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17489f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17499f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17509f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley break; 1754d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1755d71ae5a4SJacob Faibussowitsch break; 1756d71ae5a4SJacob Faibussowitsch default: 1757d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1758e5c487bfSMatthew G. Knepley } 17593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1760e5c487bfSMatthew G. Knepley } 1761e5c487bfSMatthew G. Knepley 1762c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1763d71ae5a4SJacob Faibussowitsch { 1764e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1765e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1766c5aedaa3SMatthew G. Knepley PetscInt fillColor; 1767e5c487bfSMatthew G. Knepley 1768e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1770e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1771c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1772c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1773c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 17749371c9d4SSatish Balay } 1775c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1776e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1777e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1778c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1779c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1780c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1781e5c487bfSMatthew G. Knepley } 17829566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1783c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 17849566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], fillColor, fillColor, fillColor)); 17859566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, edgeCoords[d * 2 + 0], edgeCoords[d * 2 + 1], edgeCoords[(d + 1) * 2 + 0], edgeCoords[(d + 1) * 2 + 1], PETSC_DRAW_BLACK)); 1786e5c487bfSMatthew G. Knepley } 1787e5c487bfSMatthew G. Knepley } 1788c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1789c5aedaa3SMatthew G. Knepley } 1790c5aedaa3SMatthew G. Knepley 1791c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1792c5aedaa3SMatthew G. Knepley { 1793c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1794c5aedaa3SMatthew G. Knepley 1795c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1796c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1797c5aedaa3SMatthew G. Knepley switch (ct) { 1798c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1799c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1800c5aedaa3SMatthew G. Knepley 1801c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1802c5aedaa3SMatthew G. Knepley } break; 1803c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1804c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1805c5aedaa3SMatthew G. Knepley 1806c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 18079371c9d4SSatish Balay } break; 1808d71ae5a4SJacob Faibussowitsch default: 1809d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1810e5c487bfSMatthew G. Knepley } 18113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1812e5c487bfSMatthew G. Knepley } 1813e5c487bfSMatthew G. Knepley 1814d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1815d71ae5a4SJacob Faibussowitsch { 1816e412dcbdSMatthew G. Knepley PetscDraw draw; 1817e412dcbdSMatthew G. Knepley DM cdm; 1818e412dcbdSMatthew G. Knepley PetscSection coordSection; 1819e412dcbdSMatthew G. Knepley Vec coordinates; 1820c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1821e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1822c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1823c5aedaa3SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv; 1824e412dcbdSMatthew G. Knepley 1825e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 182763a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1828c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1829c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1830c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 18319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18329566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18339566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18349566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18379566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1838e412dcbdSMatthew G. Knepley 18399566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18409566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18413ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18429566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1843e412dcbdSMatthew G. Knepley 1844c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18459566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18469566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1847e412dcbdSMatthew G. Knepley 1848cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1849cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1850c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1851ba2698f1SMatthew G. Knepley PetscInt numCoords; 1852c9c77995SMatthew G. Knepley PetscBool isDG; 1853cf3064d3SMatthew G. Knepley 1854c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18551baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18561baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1857c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1858cf3064d3SMatthew G. Knepley } 18599566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18609566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18619566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18629566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1864e412dcbdSMatthew G. Knepley } 1865e412dcbdSMatthew G. Knepley 1866e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1867e44f6aebSMatthew G. Knepley { 1868e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1869e44f6aebSMatthew G. Knepley PetscFE fe; 1870e44f6aebSMatthew G. Knepley PetscSpace sp; 1871e44f6aebSMatthew G. Knepley PetscClassId id; 1872e44f6aebSMatthew G. Knepley PetscInt degree; 1873e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1874e44f6aebSMatthew G. Knepley 1875e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1876e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1877e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1878e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1879e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1880e44f6aebSMatthew G. Knepley *hdm = dm; 1881e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1882e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1883e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1884e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1885e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1886e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1887e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1888e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1889e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1890e44f6aebSMatthew G. Knepley Mat In; 1891e44f6aebSMatthew G. Knepley Vec cl, rcl; 1892e44f6aebSMatthew G. Knepley 1893e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1894c5aedaa3SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1895e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1896e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1897e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1898e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1899e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1900e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1901e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1902e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1903e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1904e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1905e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1906e44f6aebSMatthew G. Knepley odm = rdm; 1907e44f6aebSMatthew G. Knepley } 1908e44f6aebSMatthew G. Knepley *hdm = rdm; 1909e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1910e44f6aebSMatthew G. Knepley } 1911e44f6aebSMatthew G. Knepley 19121e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19131e50132fSMatthew G. Knepley #include <exodusII.h> 19146823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19151e50132fSMatthew G. Knepley #endif 19161e50132fSMatthew G. Knepley 1917d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1918d71ae5a4SJacob Faibussowitsch { 19195f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1920002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1921552f7358SJed Brown 1922552f7358SJed Brown PetscFunctionBegin; 1923552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1924552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19315f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1932552f7358SJed Brown if (iascii) { 19338135c375SStefano Zampini PetscViewerFormat format; 19349566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19351baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19361baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1937c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1938c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19399566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1940c6ccd67eSMatthew G. Knepley #else 1941c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1942552f7358SJed Brown #endif 1943e412dcbdSMatthew G. Knepley } else if (isvtk) { 19449566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1945e412dcbdSMatthew G. Knepley } else if (isdraw) { 1946e44f6aebSMatthew G. Knepley DM hdm; 1947e44f6aebSMatthew G. Knepley 1948e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1949e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1950e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19518135c375SStefano Zampini } else if (isglvis) { 19529566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19531e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19541e50132fSMatthew G. Knepley } else if (isexodus) { 19556823f3c5SBlaise Bourdin /* 19566823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19576823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1958da81f932SPierre Jolivet with ID 1, containing all cells. 19596823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19606823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19616823f3c5SBlaise Bourdin */ 19626823f3c5SBlaise Bourdin PetscInt numCS; 19639566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19646823f3c5SBlaise Bourdin if (!numCS) { 19651e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19669566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19679566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19689566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19696823f3c5SBlaise Bourdin } 19709566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19711e50132fSMatthew G. Knepley #endif 19725f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19735f34f2dcSJed Brown } else if (iscgns) { 19745f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19755f34f2dcSJed Brown #endif 19761baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1977cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19789566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1979cb3ba0daSMatthew G. Knepley if (flg) { 1980cb3ba0daSMatthew G. Knepley Vec ranks; 19819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19829566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1984cb3ba0daSMatthew G. Knepley } 1985002a2709SMatthew G. Knepley /* Optionally view a label */ 19869566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1987002a2709SMatthew G. Knepley if (flg) { 1988002a2709SMatthew G. Knepley DMLabel label; 1989002a2709SMatthew G. Knepley Vec val; 1990002a2709SMatthew G. Knepley 19919566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 199228b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19949566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1996002a2709SMatthew G. Knepley } 19973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1998552f7358SJed Brown } 1999552f7358SJed Brown 20007f96f51bSksagiyam /*@ 2001a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 20027f96f51bSksagiyam 200320f4b53cSBarry Smith Collective 20047f96f51bSksagiyam 20057f96f51bSksagiyam Input Parameters: 2006a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2007a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 20087f96f51bSksagiyam 20097f96f51bSksagiyam Level: advanced 20107f96f51bSksagiyam 20111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 20127f96f51bSksagiyam @*/ 2013d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2014d71ae5a4SJacob Faibussowitsch { 20157f96f51bSksagiyam PetscBool ishdf5; 20167f96f51bSksagiyam 20177f96f51bSksagiyam PetscFunctionBegin; 20187f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20197f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20219566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20227f96f51bSksagiyam if (ishdf5) { 20237f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20247f96f51bSksagiyam PetscViewerFormat format; 20259566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20267f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20277f96f51bSksagiyam IS globalPointNumbering; 20287f96f51bSksagiyam 20299566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20309566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 203298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20337f96f51bSksagiyam #else 20347f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20357f96f51bSksagiyam #endif 20367f96f51bSksagiyam } 20379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20397f96f51bSksagiyam } 20407f96f51bSksagiyam 204177b8e257Sksagiyam /*@ 2042a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 204377b8e257Sksagiyam 204420f4b53cSBarry Smith Collective 204577b8e257Sksagiyam 204677b8e257Sksagiyam Input Parameters: 2047a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2048a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 204977b8e257Sksagiyam 205077b8e257Sksagiyam Level: advanced 205177b8e257Sksagiyam 20521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 205377b8e257Sksagiyam @*/ 2054d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2055d71ae5a4SJacob Faibussowitsch { 205677b8e257Sksagiyam PetscBool ishdf5; 205777b8e257Sksagiyam 205877b8e257Sksagiyam PetscFunctionBegin; 205977b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 206077b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 206377b8e257Sksagiyam if (ishdf5) { 206477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 206577b8e257Sksagiyam PetscViewerFormat format; 20669566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 206777b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20689566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2069fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 207077b8e257Sksagiyam #else 207177b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 207277b8e257Sksagiyam #endif 207377b8e257Sksagiyam } 20749566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207677b8e257Sksagiyam } 207777b8e257Sksagiyam 2078bd6565f1Sksagiyam /*@ 2079a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2080bd6565f1Sksagiyam 208120f4b53cSBarry Smith Collective 2082bd6565f1Sksagiyam 2083bd6565f1Sksagiyam Input Parameters: 2084a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2085a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2086bd6565f1Sksagiyam 2087bd6565f1Sksagiyam Level: advanced 2088bd6565f1Sksagiyam 20891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2090bd6565f1Sksagiyam @*/ 2091d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2092d71ae5a4SJacob Faibussowitsch { 2093bd6565f1Sksagiyam PetscBool ishdf5; 2094bd6565f1Sksagiyam 2095bd6565f1Sksagiyam PetscFunctionBegin; 2096bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2097bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20999566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2100bd6565f1Sksagiyam if (ishdf5) { 2101bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2102bd6565f1Sksagiyam IS globalPointNumbering; 2103bd6565f1Sksagiyam PetscViewerFormat format; 2104bd6565f1Sksagiyam 21059566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2106bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21079566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21089566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 211098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2111bd6565f1Sksagiyam #else 2112bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2113bd6565f1Sksagiyam #endif 2114bd6565f1Sksagiyam } 21159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2117bd6565f1Sksagiyam } 2118bd6565f1Sksagiyam 2119021affd3Sksagiyam /*@ 2120a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2121021affd3Sksagiyam 212220f4b53cSBarry Smith Collective 2123021affd3Sksagiyam 2124021affd3Sksagiyam Input Parameters: 2125a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2126a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 21270318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2128021affd3Sksagiyam 2129021affd3Sksagiyam Level: advanced 2130021affd3Sksagiyam 2131021affd3Sksagiyam Notes: 2132420bcc1bSBarry Smith This function is a wrapper around `PetscSectionView()`; in addition to the raw section, it saves information that associates the section points to the topology (`dm`) points. When the topology (`dm`) and the section are later loaded with `DMPlexTopologyLoad()` and `DMPlexSectionLoad()`, respectively, this information is used to match section points with topology points. 2133021affd3Sksagiyam 21340318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2135021affd3Sksagiyam 21361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2137021affd3Sksagiyam @*/ 2138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2139d71ae5a4SJacob Faibussowitsch { 2140021affd3Sksagiyam PetscBool ishdf5; 2141021affd3Sksagiyam 2142021affd3Sksagiyam PetscFunctionBegin; 2143021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2144021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21450318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2146021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2149021affd3Sksagiyam if (ishdf5) { 2150021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21519566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2152021affd3Sksagiyam #else 2153021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2154021affd3Sksagiyam #endif 2155021affd3Sksagiyam } 21569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2158021affd3Sksagiyam } 2159021affd3Sksagiyam 21603e97647fSksagiyam /*@ 21613e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21623e97647fSksagiyam 216320f4b53cSBarry Smith Collective 21643e97647fSksagiyam 21653e97647fSksagiyam Input Parameters: 2166a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2167a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 21680318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 21693e97647fSksagiyam - vec - The global vector to be saved 21703e97647fSksagiyam 21713e97647fSksagiyam Level: advanced 21723e97647fSksagiyam 21733e97647fSksagiyam Notes: 21740318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 21753e97647fSksagiyam 217660225df5SJacob Faibussowitsch Calling sequence: 2177a1cb98faSBarry Smith .vb 2178a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2179a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2180a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2181a1cb98faSBarry Smith DMClone(dm, §iondm); 2182a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2183a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2184a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2185a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2186a1cb98faSBarry Smith PetscSectionSetUp(section); 2187a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2188a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2189a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2190a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2191a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2192a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2193a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2194a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2195a1cb98faSBarry Smith DMDestroy(§iondm); 2196a1cb98faSBarry Smith DMDestroy(&dm); 2197a1cb98faSBarry Smith .ve 21983e97647fSksagiyam 21991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22003e97647fSksagiyam @*/ 2201d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2202d71ae5a4SJacob Faibussowitsch { 22033e97647fSksagiyam PetscBool ishdf5; 22043e97647fSksagiyam 22053e97647fSksagiyam PetscFunctionBegin; 22063e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22073e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22080318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22093e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22103e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22113e97647fSksagiyam /* Check consistency */ 22123e97647fSksagiyam { 22133e97647fSksagiyam PetscSection section; 22143e97647fSksagiyam PetscBool includesConstraints; 22153e97647fSksagiyam PetscInt m, m1; 22163e97647fSksagiyam 22179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22189566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22209566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22219566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 222263a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22233e97647fSksagiyam } 22249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22263e97647fSksagiyam if (ishdf5) { 22273e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22289566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22293e97647fSksagiyam #else 22303e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22313e97647fSksagiyam #endif 22323e97647fSksagiyam } 22339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22353e97647fSksagiyam } 22363e97647fSksagiyam 22373e97647fSksagiyam /*@ 22383e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22393e97647fSksagiyam 224020f4b53cSBarry Smith Collective 22413e97647fSksagiyam 22423e97647fSksagiyam Input Parameters: 2243a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2244a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 22463e97647fSksagiyam - vec - The local vector to be saved 22473e97647fSksagiyam 22483e97647fSksagiyam Level: advanced 22493e97647fSksagiyam 2250a1cb98faSBarry Smith Note: 22510318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 22523e97647fSksagiyam 225360225df5SJacob Faibussowitsch Calling sequence: 2254a1cb98faSBarry Smith .vb 2255a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2256a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2257a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2258a1cb98faSBarry Smith DMClone(dm, §iondm); 2259a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2260a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2261a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2262a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2263a1cb98faSBarry Smith PetscSectionSetUp(section); 2264a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2265a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2266a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2267a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2268a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2269a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2270a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2271a1cb98faSBarry Smith DMDestroy(§iondm); 2272a1cb98faSBarry Smith DMDestroy(&dm); 2273a1cb98faSBarry Smith .ve 22743e97647fSksagiyam 22751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22763e97647fSksagiyam @*/ 2277d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2278d71ae5a4SJacob Faibussowitsch { 22793e97647fSksagiyam PetscBool ishdf5; 22803e97647fSksagiyam 22813e97647fSksagiyam PetscFunctionBegin; 22823e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22833e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22840318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22853e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22863e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22873e97647fSksagiyam /* Check consistency */ 22883e97647fSksagiyam { 22893e97647fSksagiyam PetscSection section; 22903e97647fSksagiyam PetscBool includesConstraints; 22913e97647fSksagiyam PetscInt m, m1; 22923e97647fSksagiyam 22939566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22949566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22969566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22979566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 229863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 22993e97647fSksagiyam } 23009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23023e97647fSksagiyam if (ishdf5) { 23033e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23049566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23053e97647fSksagiyam #else 23063e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23073e97647fSksagiyam #endif 23083e97647fSksagiyam } 23099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23113e97647fSksagiyam } 23123e97647fSksagiyam 2313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2314d71ae5a4SJacob Faibussowitsch { 2315d4f5a9a0SVaclav Hapla PetscBool ishdf5; 23162c40f234SMatthew G. Knepley 23172c40f234SMatthew G. Knepley PetscFunctionBegin; 23182c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23192c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2321d4f5a9a0SVaclav Hapla if (ishdf5) { 23222c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23239c48423bSVaclav Hapla PetscViewerFormat format; 23249566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23259c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23269566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2327509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23289566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 232998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23312c40f234SMatthew G. Knepley #else 23322c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2333552f7358SJed Brown #endif 233498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2335552f7358SJed Brown } 2336552f7358SJed Brown 2337ea8e1828Sksagiyam /*@ 2338a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2339ea8e1828Sksagiyam 234020f4b53cSBarry Smith Collective 2341ea8e1828Sksagiyam 2342ea8e1828Sksagiyam Input Parameters: 2343a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2344a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2345ea8e1828Sksagiyam 23462fe279fdSBarry Smith Output Parameter: 234720f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded 2348dec9e869Sksagiyam 2349ea8e1828Sksagiyam Level: advanced 2350ea8e1828Sksagiyam 23511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2352a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2353ea8e1828Sksagiyam @*/ 2354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2355d71ae5a4SJacob Faibussowitsch { 2356ea8e1828Sksagiyam PetscBool ishdf5; 2357ea8e1828Sksagiyam 2358ea8e1828Sksagiyam PetscFunctionBegin; 2359ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2360ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23614f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2364ea8e1828Sksagiyam if (ishdf5) { 2365ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2366ea8e1828Sksagiyam PetscViewerFormat format; 23679566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2368ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23699566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 237098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2371ea8e1828Sksagiyam #else 2372ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2373ea8e1828Sksagiyam #endif 2374ea8e1828Sksagiyam } 23759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2377ea8e1828Sksagiyam } 2378ea8e1828Sksagiyam 23793e701f1cSksagiyam /*@ 2380a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23813e701f1cSksagiyam 238220f4b53cSBarry Smith Collective 23833e701f1cSksagiyam 23843e701f1cSksagiyam Input Parameters: 2385a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2386a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2387a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23883e701f1cSksagiyam 23893e701f1cSksagiyam Level: advanced 23903e701f1cSksagiyam 23911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2392a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23933e701f1cSksagiyam @*/ 2394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2395d71ae5a4SJacob Faibussowitsch { 23963e701f1cSksagiyam PetscBool ishdf5; 23973e701f1cSksagiyam 23983e701f1cSksagiyam PetscFunctionBegin; 23993e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24003e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2401c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24043e701f1cSksagiyam if (ishdf5) { 24053e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 24063e701f1cSksagiyam PetscViewerFormat format; 24079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24083e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24099566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 241098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24113e701f1cSksagiyam #else 24123e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24133e701f1cSksagiyam #endif 24143e701f1cSksagiyam } 24159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24173e701f1cSksagiyam } 24183e701f1cSksagiyam 2419b08ad5deSksagiyam /*@ 2420a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2421b08ad5deSksagiyam 242220f4b53cSBarry Smith Collective 2423b08ad5deSksagiyam 2424b08ad5deSksagiyam Input Parameters: 2425a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2426a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 242720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2428b08ad5deSksagiyam 2429b08ad5deSksagiyam Level: advanced 2430b08ad5deSksagiyam 2431a1cb98faSBarry Smith Note: 2432a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2433e6368b79SVaclav Hapla 24341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2435a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2436b08ad5deSksagiyam @*/ 2437d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2438d71ae5a4SJacob Faibussowitsch { 2439b08ad5deSksagiyam PetscBool ishdf5; 2440b08ad5deSksagiyam 2441b08ad5deSksagiyam PetscFunctionBegin; 2442b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2443b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2444e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2447b08ad5deSksagiyam if (ishdf5) { 2448b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2449b08ad5deSksagiyam PetscViewerFormat format; 2450b08ad5deSksagiyam 24519566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2452b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24539566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 245498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2455b08ad5deSksagiyam #else 2456b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2457b08ad5deSksagiyam #endif 2458b08ad5deSksagiyam } 24599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2461b08ad5deSksagiyam } 2462b08ad5deSksagiyam 2463f84dd6b4Sksagiyam /*@ 2464a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2465f84dd6b4Sksagiyam 246620f4b53cSBarry Smith Collective 2467f84dd6b4Sksagiyam 2468f84dd6b4Sksagiyam Input Parameters: 2469a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2470a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 24710318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2472a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2473f84dd6b4Sksagiyam 2474a4e35b19SJacob Faibussowitsch Output Parameters: 247520f4b53cSBarry Smith + globalDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a global `Vec` associated with the `sectiondm`'s global section (`NULL` if not needed) 247620f4b53cSBarry Smith - localDofSF - The `PetscSF` that migrates any on-disk `Vec` data associated with sectionA into a local `Vec` associated with the `sectiondm`'s local section (`NULL` if not needed) 2477f84dd6b4Sksagiyam 2478f84dd6b4Sksagiyam Level: advanced 2479f84dd6b4Sksagiyam 2480f84dd6b4Sksagiyam Notes: 248120f4b53cSBarry Smith This function is a wrapper around `PetscSectionLoad()`; it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in `dm`. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points. 2482f84dd6b4Sksagiyam 24830318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2484f84dd6b4Sksagiyam 248520f4b53cSBarry Smith The output parameter, `globalDofSF` (`localDofSF`), can later be used with `DMPlexGlobalVectorLoad()` (`DMPlexLocalVectorLoad()`) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section. 2486f84dd6b4Sksagiyam 2487f84dd6b4Sksagiyam Example using 2 processes: 2488a1cb98faSBarry Smith .vb 2489a1cb98faSBarry Smith NX (number of points on dm): 4 2490a1cb98faSBarry Smith sectionA : the on-disk section 2491a1cb98faSBarry Smith vecA : a vector associated with sectionA 2492a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2493a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2494a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2495f84dd6b4Sksagiyam 2496a1cb98faSBarry Smith rank 0 rank 1 2497a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2498a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2499a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2500a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2501a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2502a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2503a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2504a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2505a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2506a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2507a1cb98faSBarry Smith .ve 2508a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2509a1cb98faSBarry Smith 25101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2511f84dd6b4Sksagiyam @*/ 2512d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2513d71ae5a4SJacob Faibussowitsch { 2514f84dd6b4Sksagiyam PetscBool ishdf5; 2515f84dd6b4Sksagiyam 2516f84dd6b4Sksagiyam PetscFunctionBegin; 2517f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2518f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25190318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2520f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2521f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25224f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25234f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2526f84dd6b4Sksagiyam if (ishdf5) { 2527f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25289566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2529f84dd6b4Sksagiyam #else 2530f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2531f84dd6b4Sksagiyam #endif 2532f84dd6b4Sksagiyam } 25339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2535f84dd6b4Sksagiyam } 2536f84dd6b4Sksagiyam 25378be3dfe1Sksagiyam /*@ 25388be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25398be3dfe1Sksagiyam 254020f4b53cSBarry Smith Collective 25418be3dfe1Sksagiyam 25428be3dfe1Sksagiyam Input Parameters: 2543a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2544a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 25450318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2546a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25478be3dfe1Sksagiyam - vec - The global vector to set values of 25488be3dfe1Sksagiyam 25498be3dfe1Sksagiyam Level: advanced 25508be3dfe1Sksagiyam 25518be3dfe1Sksagiyam Notes: 25520318f8a0SStefano Zampini In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 25538be3dfe1Sksagiyam 255460225df5SJacob Faibussowitsch Calling sequence: 2555a1cb98faSBarry Smith .vb 2556a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2557a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2558a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2559a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2560a1cb98faSBarry Smith DMClone(dm, §iondm); 2561a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2562a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2563a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2564a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2565a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2566a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2567a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2568a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2569a1cb98faSBarry Smith DMDestroy(§iondm); 2570a1cb98faSBarry Smith DMDestroy(&dm); 2571a1cb98faSBarry Smith .ve 25728be3dfe1Sksagiyam 25731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2574a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25758be3dfe1Sksagiyam @*/ 2576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2577d71ae5a4SJacob Faibussowitsch { 25788be3dfe1Sksagiyam PetscBool ishdf5; 25798be3dfe1Sksagiyam 25808be3dfe1Sksagiyam PetscFunctionBegin; 25818be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25828be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25830318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 25848be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25858be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25868be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25878be3dfe1Sksagiyam /* Check consistency */ 25888be3dfe1Sksagiyam { 25898be3dfe1Sksagiyam PetscSection section; 25908be3dfe1Sksagiyam PetscBool includesConstraints; 25918be3dfe1Sksagiyam PetscInt m, m1; 25928be3dfe1Sksagiyam 25939566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25949566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25969566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25979566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 259863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 25998be3dfe1Sksagiyam } 26009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26028be3dfe1Sksagiyam if (ishdf5) { 26038be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26049566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26058be3dfe1Sksagiyam #else 26068be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26078be3dfe1Sksagiyam #endif 26088be3dfe1Sksagiyam } 26099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26118be3dfe1Sksagiyam } 26128be3dfe1Sksagiyam 26138be3dfe1Sksagiyam /*@ 26148be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 26158be3dfe1Sksagiyam 261620f4b53cSBarry Smith Collective 26178be3dfe1Sksagiyam 26188be3dfe1Sksagiyam Input Parameters: 2619a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2620a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26210318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2622a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26238be3dfe1Sksagiyam - vec - The local vector to set values of 26248be3dfe1Sksagiyam 26258be3dfe1Sksagiyam Level: advanced 26268be3dfe1Sksagiyam 26278be3dfe1Sksagiyam Notes: 26280318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 26298be3dfe1Sksagiyam 263060225df5SJacob Faibussowitsch Calling sequence: 2631a1cb98faSBarry Smith .vb 2632a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2633a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2634a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2635a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2636a1cb98faSBarry Smith DMClone(dm, §iondm); 2637a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2638a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2639a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2640a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2641a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2642a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2643a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2644a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2645a1cb98faSBarry Smith DMDestroy(§iondm); 2646a1cb98faSBarry Smith DMDestroy(&dm); 2647a1cb98faSBarry Smith .ve 26488be3dfe1Sksagiyam 26491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2650a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26518be3dfe1Sksagiyam @*/ 2652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2653d71ae5a4SJacob Faibussowitsch { 26548be3dfe1Sksagiyam PetscBool ishdf5; 26558be3dfe1Sksagiyam 26568be3dfe1Sksagiyam PetscFunctionBegin; 26578be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26588be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26590318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 26608be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26618be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26628be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26638be3dfe1Sksagiyam /* Check consistency */ 26648be3dfe1Sksagiyam { 26658be3dfe1Sksagiyam PetscSection section; 26668be3dfe1Sksagiyam PetscBool includesConstraints; 26678be3dfe1Sksagiyam PetscInt m, m1; 26688be3dfe1Sksagiyam 26699566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26709566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26729566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26739566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 267463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26758be3dfe1Sksagiyam } 26769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26788be3dfe1Sksagiyam if (ishdf5) { 26798be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26809566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26818be3dfe1Sksagiyam #else 26828be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26838be3dfe1Sksagiyam #endif 26848be3dfe1Sksagiyam } 26859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26878be3dfe1Sksagiyam } 26888be3dfe1Sksagiyam 2689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2690d71ae5a4SJacob Faibussowitsch { 2691552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2692552f7358SJed Brown 2693552f7358SJed Brown PetscFunctionBegin; 26949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26986c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 26992e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 27002e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 27012e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 27022e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 27036bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 27046bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2705adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2706adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2707adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2708adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2709c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2710c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2711d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2712d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 27135f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 27143ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 27159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 27169566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 27189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 27199566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 27209566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 272121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27229f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 27239566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27249566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27259566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27261d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27289566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27324e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27336725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27346725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27389566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27399566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27419566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27429566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27439566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27449566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27459566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2746552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27479566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2749552f7358SJed Brown } 2750552f7358SJed Brown 2751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2752d71ae5a4SJacob Faibussowitsch { 2753d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2754acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27559fca9976SJed Brown PetscInt localSize, localStart = 0; 2756837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2757b412c318SBarry Smith MatType mtype; 27581428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2759552f7358SJed Brown 2760552f7358SJed Brown PetscFunctionBegin; 27619566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2762b412c318SBarry Smith mtype = dm->mattype; 2763d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 27649566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27659566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27679fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27689566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27709566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27719566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27729566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2773acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27769566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27799566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2782552f7358SJed Brown if (!isShell) { 2783837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27849fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2785863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2786552f7358SJed Brown 27879566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27889fca9976SJed Brown 27899fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2791863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2792e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2793863027abSJed Brown switch (dm->blocking_type) { 27940e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27959fca9976SJed Brown PetscInt bdof, offset; 2796a9d99c84SMatthew G. Knepley 27979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27989fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 27999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 2800d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2801d02c7345SMatthew G. Knepley // Signal block concatenation 2802d02c7345SMatthew G. Knepley if (dof - cdof && sectionLocal->blockStarts && !PetscBTLookup(sectionLocal->blockStarts, p)) pblocks[offset - localStart] = -(dof - cdof); 28031d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 28041d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 28051d17a0a3SMatthew G. Knepley if (dof) { 28069371c9d4SSatish Balay if (bs < 0) { 28079371c9d4SSatish Balay bs = bdof; 28089371c9d4SSatish Balay } else if (bs != bdof) { 28099371c9d4SSatish Balay bs = 1; 28109371c9d4SSatish Balay } 2811552f7358SJed Brown } 2812863027abSJed Brown } break; 2813863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2814863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2815863027abSJed Brown PetscInt num_comp, bdof, offset; 2816863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2817863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2818863027abSJed Brown if (dof < 0) continue; 2819863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2820863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2821863027abSJed Brown PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp); 2822863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2823863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2824863027abSJed Brown // Handle possibly constant block size (unlikely) 2825863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2826863027abSJed Brown if (dof) { 2827863027abSJed Brown if (bs < 0) { 2828863027abSJed Brown bs = bdof; 2829863027abSJed Brown } else if (bs != bdof) { 2830863027abSJed Brown bs = 1; 2831863027abSJed Brown } 2832863027abSJed Brown } 2833863027abSJed Brown } 2834863027abSJed Brown } break; 2835863027abSJed Brown } 28362a28c762SMatthew G Knepley } 28372a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2838e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2839e432b41dSStefano Zampini bsLocal[1] = bs; 28409566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2841e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2842e432b41dSStefano Zampini else bs = bsMinMax[0]; 28436fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28449566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28450682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28469566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28479566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28480682b8bbSJed Brown } else { 28499566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28509566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28519566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2852552f7358SJed Brown } 28539fca9976SJed Brown { // Consolidate blocks 28549fca9976SJed Brown PetscInt nblocks = 0; 28559fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28569fca9976SJed Brown if (pblocks[i] == 0) continue; 2857d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2858d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2859d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2860d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2861d02c7345SMatthew G. Knepley } else { 28629fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2863d02c7345SMatthew G. Knepley } 2864ad540459SPierre Jolivet for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]); 28659fca9976SJed Brown } 28669fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28679fca9976SJed Brown } 28689fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2869aa0f6e3cSJed Brown } 28709566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2872552f7358SJed Brown } 2873552f7358SJed Brown 28747cd05799SMatthew G. Knepley /*@ 2875a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2876be36d101SStefano Zampini 2877a1cb98faSBarry Smith Not Collective 2878be36d101SStefano Zampini 2879be36d101SStefano Zampini Input Parameter: 288060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2881be36d101SStefano Zampini 28822fe279fdSBarry Smith Output Parameter: 2883be36d101SStefano Zampini . subsection - The subdomain section 2884be36d101SStefano Zampini 2885be36d101SStefano Zampini Level: developer 2886be36d101SStefano Zampini 28871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28887cd05799SMatthew G. Knepley @*/ 2889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2890d71ae5a4SJacob Faibussowitsch { 2891be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2892be36d101SStefano Zampini 2893be36d101SStefano Zampini PetscFunctionBegin; 2894be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2895be36d101SStefano Zampini if (!mesh->subdomainSection) { 2896be36d101SStefano Zampini PetscSection section; 2897be36d101SStefano Zampini PetscSF sf; 2898be36d101SStefano Zampini 28999566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 29009566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2901eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 29029566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2903be36d101SStefano Zampini } 2904be36d101SStefano Zampini *subsection = mesh->subdomainSection; 29053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2906be36d101SStefano Zampini } 2907be36d101SStefano Zampini 2908552f7358SJed Brown /*@ 290920f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2910552f7358SJed Brown 2911a1cb98faSBarry Smith Not Collective 2912552f7358SJed Brown 2913552f7358SJed Brown Input Parameter: 291460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2915552f7358SJed Brown 2916552f7358SJed Brown Output Parameters: 2917552f7358SJed Brown + pStart - The first mesh point 2918552f7358SJed Brown - pEnd - The upper bound for mesh points 2919552f7358SJed Brown 2920552f7358SJed Brown Level: beginner 2921552f7358SJed Brown 29221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2923552f7358SJed Brown @*/ 2924d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2925d71ae5a4SJacob Faibussowitsch { 2926552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2927552f7358SJed Brown 2928552f7358SJed Brown PetscFunctionBegin; 2929552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29309f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 29319f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 29323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2933552f7358SJed Brown } 2934552f7358SJed Brown 2935552f7358SJed Brown /*@ 293620f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2937552f7358SJed Brown 2938a1cb98faSBarry Smith Not Collective 2939552f7358SJed Brown 2940552f7358SJed Brown Input Parameters: 294160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2942552f7358SJed Brown . pStart - The first mesh point 2943552f7358SJed Brown - pEnd - The upper bound for mesh points 2944552f7358SJed Brown 2945552f7358SJed Brown Level: beginner 2946552f7358SJed Brown 29471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2948552f7358SJed Brown @*/ 2949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2950d71ae5a4SJacob Faibussowitsch { 2951552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2952552f7358SJed Brown 2953552f7358SJed Brown PetscFunctionBegin; 2954552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 295721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2959552f7358SJed Brown } 2960552f7358SJed Brown 2961552f7358SJed Brown /*@ 2962eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2963552f7358SJed Brown 2964a1cb98faSBarry Smith Not Collective 2965552f7358SJed Brown 2966552f7358SJed Brown Input Parameters: 296760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2968a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2969552f7358SJed Brown 2970552f7358SJed Brown Output Parameter: 297120f4b53cSBarry Smith . size - The cone size for point `p` 2972552f7358SJed Brown 2973552f7358SJed Brown Level: beginner 2974552f7358SJed Brown 29751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2976552f7358SJed Brown @*/ 2977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2978d71ae5a4SJacob Faibussowitsch { 2979552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2980552f7358SJed Brown 2981552f7358SJed Brown PetscFunctionBegin; 2982552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29834f572ea9SToby Isaac PetscAssertPointer(size, 3); 29849f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29859f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2987552f7358SJed Brown } 2988552f7358SJed Brown 2989552f7358SJed Brown /*@ 2990eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2991552f7358SJed Brown 2992a1cb98faSBarry Smith Not Collective 2993552f7358SJed Brown 2994552f7358SJed Brown Input Parameters: 299560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2996a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 299720f4b53cSBarry Smith - size - The cone size for point `p` 2998552f7358SJed Brown 2999552f7358SJed Brown Level: beginner 3000552f7358SJed Brown 3001a1cb98faSBarry Smith Note: 3002a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3003a1cb98faSBarry Smith 30041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3005552f7358SJed Brown @*/ 3006d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3007d71ae5a4SJacob Faibussowitsch { 3008552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3009552f7358SJed Brown 3010552f7358SJed Brown PetscFunctionBegin; 3011552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30129f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3015552f7358SJed Brown } 3016552f7358SJed Brown 3017552f7358SJed Brown /*@C 3018eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3019552f7358SJed Brown 3020a1cb98faSBarry Smith Not Collective 3021552f7358SJed Brown 3022552f7358SJed Brown Input Parameters: 3023a1cb98faSBarry Smith + dm - The `DMPLEX` 3024a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3025552f7358SJed Brown 3026552f7358SJed Brown Output Parameter: 302720f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 3028552f7358SJed Brown 3029552f7358SJed Brown Level: beginner 3030552f7358SJed Brown 303160225df5SJacob Faibussowitsch Fortran Notes: 3032a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3033a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30343813dfbdSMatthew G Knepley 30351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3036552f7358SJed Brown @*/ 3037d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3038d71ae5a4SJacob Faibussowitsch { 3039552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3040552f7358SJed Brown PetscInt off; 3041552f7358SJed Brown 3042552f7358SJed Brown PetscFunctionBegin; 3043552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30444f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 30468e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 30473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3048552f7358SJed Brown } 3049552f7358SJed Brown 30500ce7577fSVaclav Hapla /*@C 30510ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30520ce7577fSVaclav Hapla 3053a1cb98faSBarry Smith Not Collective 30540ce7577fSVaclav Hapla 30550ce7577fSVaclav Hapla Input Parameters: 3056a1cb98faSBarry Smith + dm - The `DMPLEX` 3057a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30580ce7577fSVaclav Hapla 3059d8d19677SJose E. Roman Output Parameters: 306020f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 306120f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30620ce7577fSVaclav Hapla 30630ce7577fSVaclav Hapla Level: intermediate 30640ce7577fSVaclav Hapla 30651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30660ce7577fSVaclav Hapla @*/ 3067d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3068d71ae5a4SJacob Faibussowitsch { 30690ce7577fSVaclav Hapla PetscSection cs, newcs; 30700ce7577fSVaclav Hapla PetscInt *cones; 30710ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30720ce7577fSVaclav Hapla PetscInt n; 30730ce7577fSVaclav Hapla 30740ce7577fSVaclav Hapla PetscFunctionBegin; 30759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30779566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30780ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30790ce7577fSVaclav Hapla if (pCones) { 30809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30820ce7577fSVaclav Hapla } 30833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30840ce7577fSVaclav Hapla } 30850ce7577fSVaclav Hapla 3086af9eab45SVaclav Hapla /*@ 3087af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3088d4636a37SVaclav Hapla 3089a1cb98faSBarry Smith Not Collective 3090d4636a37SVaclav Hapla 3091d4636a37SVaclav Hapla Input Parameters: 3092a1cb98faSBarry Smith + dm - The `DMPLEX` 3093a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3094d4636a37SVaclav Hapla 3095d4636a37SVaclav Hapla Output Parameter: 3096af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3097d4636a37SVaclav Hapla 3098d4636a37SVaclav Hapla Level: advanced 3099d4636a37SVaclav Hapla 3100af9eab45SVaclav Hapla Notes: 310120f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3102af9eab45SVaclav Hapla 3103a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3104a1cb98faSBarry Smith 31051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3106a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3107d4636a37SVaclav Hapla @*/ 3108d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3109d71ae5a4SJacob Faibussowitsch { 3110af9eab45SVaclav Hapla IS *expandedPointsAll; 3111af9eab45SVaclav Hapla PetscInt depth; 3112d4636a37SVaclav Hapla 3113d4636a37SVaclav Hapla PetscFunctionBegin; 3114af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3115af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31164f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 31179566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3118af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 31199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 31209566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 31213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3122af9eab45SVaclav Hapla } 3123af9eab45SVaclav Hapla 3124af9eab45SVaclav Hapla /*@ 3125af9eab45SVaclav Hapla DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones). 3126af9eab45SVaclav Hapla 3127a1cb98faSBarry Smith Not Collective 3128af9eab45SVaclav Hapla 3129af9eab45SVaclav Hapla Input Parameters: 3130a1cb98faSBarry Smith + dm - The `DMPLEX` 3131a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3132af9eab45SVaclav Hapla 3133d8d19677SJose E. Roman Output Parameters: 3134a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3135af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3136af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3137af9eab45SVaclav Hapla 3138af9eab45SVaclav Hapla Level: advanced 3139af9eab45SVaclav Hapla 3140af9eab45SVaclav Hapla Notes: 3141a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3142af9eab45SVaclav Hapla 3143a4e35b19SJacob Faibussowitsch Array `expandedPoints` has size equal to `depth`. Each `expandedPoints`[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points. 3144af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3145af9eab45SVaclav Hapla 3146a4e35b19SJacob Faibussowitsch Array section has size equal to `depth`. Each `PetscSection` `sections`[d] realizes mapping from `expandedPoints`[d+1] (section points) to `expandedPoints`[d] (section dofs) as follows\: 3147a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3148a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3149af9eab45SVaclav Hapla 31501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3151a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3152af9eab45SVaclav Hapla @*/ 3153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3154d71ae5a4SJacob Faibussowitsch { 3155af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3156af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3157af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3158af9eab45SVaclav Hapla IS *expandedPoints_; 3159af9eab45SVaclav Hapla PetscSection *sections_; 3160af9eab45SVaclav Hapla 3161af9eab45SVaclav Hapla PetscFunctionBegin; 3162af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3163af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31644f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31654f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31664f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31719566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3172af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3173af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31749566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3176af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31779566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3178af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3181af9eab45SVaclav Hapla } else { 31829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3183af9eab45SVaclav Hapla } 3184af9eab45SVaclav Hapla } 31859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3188af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3191af9eab45SVaclav Hapla if (cn > 1) { 31929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31939566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3194af9eab45SVaclav Hapla } else { 3195af9eab45SVaclav Hapla newarr[co] = arr[i]; 3196af9eab45SVaclav Hapla } 3197af9eab45SVaclav Hapla } 31989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3199af9eab45SVaclav Hapla arr = newarr; 3200af9eab45SVaclav Hapla n = newn; 3201af9eab45SVaclav Hapla } 32029566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3203af9eab45SVaclav Hapla *depth = depth_; 3204af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3205af9eab45SVaclav Hapla else { 32069566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32079566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3208af9eab45SVaclav Hapla } 3209af9eab45SVaclav Hapla if (sections) *sections = sections_; 3210af9eab45SVaclav Hapla else { 32119566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32129566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3213af9eab45SVaclav Hapla } 32143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3215af9eab45SVaclav Hapla } 3216af9eab45SVaclav Hapla 3217af9eab45SVaclav Hapla /*@ 3218a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3219af9eab45SVaclav Hapla 3220a1cb98faSBarry Smith Not Collective 3221af9eab45SVaclav Hapla 3222af9eab45SVaclav Hapla Input Parameters: 3223a1cb98faSBarry Smith + dm - The `DMPLEX` 3224a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3225af9eab45SVaclav Hapla 3226d8d19677SJose E. Roman Output Parameters: 3227a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3228af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3229af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3230af9eab45SVaclav Hapla 3231af9eab45SVaclav Hapla Level: advanced 3232af9eab45SVaclav Hapla 3233a1cb98faSBarry Smith Note: 3234a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3235af9eab45SVaclav Hapla 32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3237a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3238af9eab45SVaclav Hapla @*/ 3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3240d71ae5a4SJacob Faibussowitsch { 3241af9eab45SVaclav Hapla PetscInt d, depth_; 3242af9eab45SVaclav Hapla 3243af9eab45SVaclav Hapla PetscFunctionBegin; 32449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32451dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3246af9eab45SVaclav Hapla if (depth) *depth = 0; 3247af9eab45SVaclav Hapla if (expandedPoints) { 32489566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32499566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3250af9eab45SVaclav Hapla } 3251af9eab45SVaclav Hapla if (sections) { 32529566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32539566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3254af9eab45SVaclav Hapla } 32553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3256d4636a37SVaclav Hapla } 3257d4636a37SVaclav Hapla 3258552f7358SJed Brown /*@ 325992371b87SBarry Smith DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point 3260552f7358SJed Brown 3261a1cb98faSBarry Smith Not Collective 3262552f7358SJed Brown 3263552f7358SJed Brown Input Parameters: 326460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3265a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 326620f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3267552f7358SJed Brown 3268552f7358SJed Brown Level: beginner 3269552f7358SJed Brown 3270a1cb98faSBarry Smith Note: 3271a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3272a1cb98faSBarry Smith 32731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3274552f7358SJed Brown @*/ 3275d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3276d71ae5a4SJacob Faibussowitsch { 3277552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3278552f7358SJed Brown PetscInt dof, off, c; 3279552f7358SJed Brown 3280552f7358SJed Brown PetscFunctionBegin; 3281552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32834f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3285db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3286db485b19SStefano Zampini PetscInt pStart, pEnd; 3287db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 328863a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3289552f7358SJed Brown for (c = 0; c < dof; ++c) { 329063a3b9bcSJacob Faibussowitsch PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd); 3291552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3292552f7358SJed Brown } 3293db485b19SStefano Zampini } else { 3294db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3295db485b19SStefano Zampini } 32963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3297552f7358SJed Brown } 3298552f7358SJed Brown 3299552f7358SJed Brown /*@C 3300eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3301552f7358SJed Brown 3302a1cb98faSBarry Smith Not Collective 3303552f7358SJed Brown 3304552f7358SJed Brown Input Parameters: 330560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3306a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3307552f7358SJed Brown 3308552f7358SJed Brown Output Parameter: 330920f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3310b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3311552f7358SJed Brown 3312552f7358SJed Brown Level: beginner 3313552f7358SJed Brown 3314a1cb98faSBarry Smith Note: 3315b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3316b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3317a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3318b5a892a1SMatthew G. Knepley with the identity. 3319b5a892a1SMatthew G. Knepley 332060225df5SJacob Faibussowitsch Fortran Notes: 3321a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3322a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 33233813dfbdSMatthew G Knepley 33241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3325552f7358SJed Brown @*/ 3326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3327d71ae5a4SJacob Faibussowitsch { 3328552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3329552f7358SJed Brown PetscInt off; 3330552f7358SJed Brown 3331552f7358SJed Brown PetscFunctionBegin; 3332552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 333376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3334552f7358SJed Brown PetscInt dof; 33359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33364f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3337552f7358SJed Brown } 33389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33390d644c17SKarl Rupp 3340552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3342552f7358SJed Brown } 3343552f7358SJed Brown 3344552f7358SJed Brown /*@ 3345eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3346552f7358SJed Brown 3347a1cb98faSBarry Smith Not Collective 3348552f7358SJed Brown 3349552f7358SJed Brown Input Parameters: 335060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3351a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3352b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3353b5a892a1SMatthew G. Knepley 3354552f7358SJed Brown Level: beginner 3355552f7358SJed Brown 3356a1cb98faSBarry Smith Notes: 3357a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3358a1cb98faSBarry Smith 3359a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3360a1cb98faSBarry Smith 33611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3362552f7358SJed Brown @*/ 3363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3364d71ae5a4SJacob Faibussowitsch { 3365552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3366552f7358SJed Brown PetscInt pStart, pEnd; 3367552f7358SJed Brown PetscInt dof, off, c; 3368552f7358SJed Brown 3369552f7358SJed Brown PetscFunctionBegin; 3370552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33724f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3374db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3375db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 337663a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3377552f7358SJed Brown for (c = 0; c < dof; ++c) { 3378552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3379552f7358SJed Brown 33809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33811dca8a05SBarry Smith PetscCheck(!o || (o >= -(cdof + 1) && o < cdof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof + 1), cdof); 3382552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3383552f7358SJed Brown } 3384db485b19SStefano Zampini } else { 3385db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3386db485b19SStefano Zampini } 33873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3388552f7358SJed Brown } 3389552f7358SJed Brown 33907cd05799SMatthew G. Knepley /*@ 3391eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33927cd05799SMatthew G. Knepley 3393a1cb98faSBarry Smith Not Collective 33947cd05799SMatthew G. Knepley 33957cd05799SMatthew G. Knepley Input Parameters: 339660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3397a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33987cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 33997cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 34007cd05799SMatthew G. Knepley 34017cd05799SMatthew G. Knepley Level: beginner 34027cd05799SMatthew G. Knepley 34031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34047cd05799SMatthew G. Knepley @*/ 3405d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3406d71ae5a4SJacob Faibussowitsch { 3407552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3408552f7358SJed Brown PetscInt pStart, pEnd; 3409552f7358SJed Brown PetscInt dof, off; 3410552f7358SJed Brown 3411552f7358SJed Brown PetscFunctionBegin; 3412552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3413a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 341563a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 341663a3b9bcSJacob Faibussowitsch PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd); 34179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 341863a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3419a03d55ffSStefano Zampini } 3420a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3421552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 34223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3423552f7358SJed Brown } 3424552f7358SJed Brown 34257cd05799SMatthew G. Knepley /*@ 3426eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 34277cd05799SMatthew G. Knepley 3428a1cb98faSBarry Smith Not Collective 34297cd05799SMatthew G. Knepley 34307cd05799SMatthew G. Knepley Input Parameters: 343160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3432a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34337cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34347cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34357cd05799SMatthew G. Knepley 34367cd05799SMatthew G. Knepley Level: beginner 34377cd05799SMatthew G. Knepley 3438a1cb98faSBarry Smith Note: 3439a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3440b5a892a1SMatthew G. Knepley 34411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34427cd05799SMatthew G. Knepley @*/ 3443d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3444d71ae5a4SJacob Faibussowitsch { 344577c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 344677c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 344777c88f5bSMatthew G Knepley PetscInt dof, off; 344877c88f5bSMatthew G Knepley 344977c88f5bSMatthew G Knepley PetscFunctionBegin; 345077c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3451a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 345363a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 34549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 345563a3b9bcSJacob Faibussowitsch PetscCheck(!(conePos < 0) && !(conePos >= dof), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof); 3456a03d55ffSStefano Zampini } 3457a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 345877c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 346077c88f5bSMatthew G Knepley } 346177c88f5bSMatthew G Knepley 34629f4ada15SMatthew G. Knepley /*@C 34639f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34649f4ada15SMatthew G. Knepley 34659f4ada15SMatthew G. Knepley Not collective 34669f4ada15SMatthew G. Knepley 34679f4ada15SMatthew G. Knepley Input Parameters: 34689f4ada15SMatthew G. Knepley + dm - The DMPlex 34699f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34709f4ada15SMatthew G. Knepley 34719f4ada15SMatthew G. Knepley Output Parameters: 347220f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 347320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34749f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34759f4ada15SMatthew G. Knepley 34769f4ada15SMatthew G. Knepley Level: beginner 34779f4ada15SMatthew G. Knepley 34789f4ada15SMatthew G. Knepley Notes: 34799f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34809f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 348120f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34829f4ada15SMatthew G. Knepley with the identity. 34839f4ada15SMatthew G. Knepley 34849f4ada15SMatthew G. Knepley Fortran Notes: 348520f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 348620f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34879f4ada15SMatthew G. Knepley 34881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34899f4ada15SMatthew G. Knepley @*/ 34909f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34919f4ada15SMatthew G. Knepley { 34929f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34939f4ada15SMatthew G. Knepley 34949f4ada15SMatthew G. Knepley PetscFunctionBegin; 34959f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34969f4ada15SMatthew G. Knepley if (mesh->tr) { 34979f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34989f4ada15SMatthew G. Knepley } else { 34999f4ada15SMatthew G. Knepley PetscInt off; 35009f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 35019f4ada15SMatthew G. Knepley PetscInt dof; 35029f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35039f4ada15SMatthew G. Knepley if (dof) { 35044f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 35054f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35069f4ada15SMatthew G. Knepley } 35079f4ada15SMatthew G. Knepley } 35089f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 35098e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 35108e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 35119f4ada15SMatthew G. Knepley } 35123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35139f4ada15SMatthew G. Knepley } 35149f4ada15SMatthew G. Knepley 35159f4ada15SMatthew G. Knepley /*@C 35169f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 35179f4ada15SMatthew G. Knepley 351820f4b53cSBarry Smith Not Collective 35199f4ada15SMatthew G. Knepley 35209f4ada15SMatthew G. Knepley Input Parameters: 35219f4ada15SMatthew G. Knepley + dm - The DMPlex 352220f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35239f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 352420f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35259f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35269f4ada15SMatthew G. Knepley 35279f4ada15SMatthew G. Knepley Level: beginner 35289f4ada15SMatthew G. Knepley 35299f4ada15SMatthew G. Knepley Notes: 35309f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35319f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 353220f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35339f4ada15SMatthew G. Knepley with the identity. 35349f4ada15SMatthew G. Knepley 353560225df5SJacob Faibussowitsch Fortran Notes: 353620f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 353720f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35389f4ada15SMatthew G. Knepley 35391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35409f4ada15SMatthew G. Knepley @*/ 35419f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35429f4ada15SMatthew G. Knepley { 35439f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35449f4ada15SMatthew G. Knepley 35459f4ada15SMatthew G. Knepley PetscFunctionBegin; 35469f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35479f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35499f4ada15SMatthew G. Knepley } 35509f4ada15SMatthew G. Knepley 3551552f7358SJed Brown /*@ 3552eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3553552f7358SJed Brown 3554a1cb98faSBarry Smith Not Collective 3555552f7358SJed Brown 3556552f7358SJed Brown Input Parameters: 355760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3558a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3559552f7358SJed Brown 3560552f7358SJed Brown Output Parameter: 356120f4b53cSBarry Smith . size - The support size for point `p` 3562552f7358SJed Brown 3563552f7358SJed Brown Level: beginner 3564552f7358SJed Brown 35651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3566552f7358SJed Brown @*/ 3567d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3568d71ae5a4SJacob Faibussowitsch { 3569552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3570552f7358SJed Brown 3571552f7358SJed Brown PetscFunctionBegin; 3572552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35734f572ea9SToby Isaac PetscAssertPointer(size, 3); 35749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3576552f7358SJed Brown } 3577552f7358SJed Brown 3578552f7358SJed Brown /*@ 3579eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3580552f7358SJed Brown 3581a1cb98faSBarry Smith Not Collective 3582552f7358SJed Brown 3583552f7358SJed Brown Input Parameters: 358460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3585a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 358620f4b53cSBarry Smith - size - The support size for point `p` 3587552f7358SJed Brown 3588a1cb98faSBarry Smith Level: beginner 3589552f7358SJed Brown 3590552f7358SJed Brown Note: 359120f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3592552f7358SJed Brown 35931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3594552f7358SJed Brown @*/ 3595d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3596d71ae5a4SJacob Faibussowitsch { 3597552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3598552f7358SJed Brown 3599552f7358SJed Brown PetscFunctionBegin; 3600552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 36023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3603552f7358SJed Brown } 3604552f7358SJed Brown 3605552f7358SJed Brown /*@C 3606eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3607552f7358SJed Brown 3608a1cb98faSBarry Smith Not Collective 3609552f7358SJed Brown 3610552f7358SJed Brown Input Parameters: 361160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3612a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3613552f7358SJed Brown 3614552f7358SJed Brown Output Parameter: 361520f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3616552f7358SJed Brown 3617552f7358SJed Brown Level: beginner 3618552f7358SJed Brown 361960225df5SJacob Faibussowitsch Fortran Notes: 3620a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3621a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 36223813dfbdSMatthew G Knepley 36231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3624552f7358SJed Brown @*/ 3625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3626d71ae5a4SJacob Faibussowitsch { 3627552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3628552f7358SJed Brown PetscInt off; 3629552f7358SJed Brown 3630552f7358SJed Brown PetscFunctionBegin; 3631552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36324f572ea9SToby Isaac PetscAssertPointer(support, 3); 36339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 36348e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 36353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3636552f7358SJed Brown } 3637552f7358SJed Brown 3638552f7358SJed Brown /*@ 363992371b87SBarry Smith DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers 3640552f7358SJed Brown 3641a1cb98faSBarry Smith Not Collective 3642552f7358SJed Brown 3643552f7358SJed Brown Input Parameters: 364460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3645a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 364620f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3647552f7358SJed Brown 3648552f7358SJed Brown Level: beginner 3649552f7358SJed Brown 3650a1cb98faSBarry Smith Note: 3651a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3652a1cb98faSBarry Smith 36531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3654552f7358SJed Brown @*/ 3655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3656d71ae5a4SJacob Faibussowitsch { 3657552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3658552f7358SJed Brown PetscInt pStart, pEnd; 3659552f7358SJed Brown PetscInt dof, off, c; 3660552f7358SJed Brown 3661552f7358SJed Brown PetscFunctionBegin; 3662552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36654f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 366763a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 3668552f7358SJed Brown for (c = 0; c < dof; ++c) { 366963a3b9bcSJacob Faibussowitsch PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd); 3670552f7358SJed Brown mesh->supports[off + c] = support[c]; 3671552f7358SJed Brown } 36723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3673552f7358SJed Brown } 3674552f7358SJed Brown 36757cd05799SMatthew G. Knepley /*@ 3676eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36777cd05799SMatthew G. Knepley 3678a1cb98faSBarry Smith Not Collective 36797cd05799SMatthew G. Knepley 36807cd05799SMatthew G. Knepley Input Parameters: 368160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3682a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36837cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36847cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36857cd05799SMatthew G. Knepley 36867cd05799SMatthew G. Knepley Level: beginner 36877cd05799SMatthew G. Knepley 36881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36897cd05799SMatthew G. Knepley @*/ 3690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3691d71ae5a4SJacob Faibussowitsch { 3692552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3693552f7358SJed Brown PetscInt pStart, pEnd; 3694552f7358SJed Brown PetscInt dof, off; 3695552f7358SJed Brown 3696552f7358SJed Brown PetscFunctionBegin; 3697552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 370163a3b9bcSJacob Faibussowitsch PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 370263a3b9bcSJacob Faibussowitsch PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd); 370363a3b9bcSJacob Faibussowitsch PetscCheck(supportPos < dof, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof); 3704552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 37053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3706552f7358SJed Brown } 3707552f7358SJed Brown 3708b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3709d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3710d71ae5a4SJacob Faibussowitsch { 3711b5a892a1SMatthew G. Knepley switch (ct) { 3712b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3713b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3714b5a892a1SMatthew G. Knepley break; 3715b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3716b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3717b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3718b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3719b5a892a1SMatthew G. Knepley break; 3720b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3721b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3722b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3723b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3724b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3725b5a892a1SMatthew G. Knepley break; 3726d71ae5a4SJacob Faibussowitsch default: 3727d71ae5a4SJacob Faibussowitsch return o; 3728b5a892a1SMatthew G. Knepley } 3729b5a892a1SMatthew G. Knepley return o; 3730b5a892a1SMatthew G. Knepley } 3731b5a892a1SMatthew G. Knepley 3732b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3733d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3734d71ae5a4SJacob Faibussowitsch { 3735b5a892a1SMatthew G. Knepley switch (ct) { 3736b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3737b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3738b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3739b5a892a1SMatthew G. Knepley break; 3740b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3741b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3742b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3743b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3744b5a892a1SMatthew G. Knepley break; 3745b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3746b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3747b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3748b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3749b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3750b5a892a1SMatthew G. Knepley break; 3751d71ae5a4SJacob Faibussowitsch default: 3752d71ae5a4SJacob Faibussowitsch return o; 3753b5a892a1SMatthew G. Knepley } 3754b5a892a1SMatthew G. Knepley return o; 3755b5a892a1SMatthew G. Knepley } 3756b5a892a1SMatthew G. Knepley 3757b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3759d71ae5a4SJacob Faibussowitsch { 3760b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3761b5a892a1SMatthew G. Knepley 3762b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3764b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3765b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3766b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3767b5a892a1SMatthew G. Knepley 37689566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3771b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3772b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3773b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3774b5a892a1SMatthew G. Knepley 37759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3776b5a892a1SMatthew G. Knepley switch (ct) { 3777b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37789566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37799566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3780b5a892a1SMatthew G. Knepley break; 3781b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37829566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37839566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37849566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3785b5a892a1SMatthew G. Knepley break; 3786b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37879566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37889566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37899566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37909566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3791b5a892a1SMatthew G. Knepley break; 3792d71ae5a4SJacob Faibussowitsch default: 3793d71ae5a4SJacob Faibussowitsch break; 3794b5a892a1SMatthew G. Knepley } 3795b5a892a1SMatthew G. Knepley } 3796b5a892a1SMatthew G. Knepley } 37973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3798b5a892a1SMatthew G. Knepley } 3799b5a892a1SMatthew G. Knepley 380009015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 380109015e70SStefano Zampini { 380209015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 380309015e70SStefano Zampini 380409015e70SStefano Zampini PetscFunctionBeginHot; 380509015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 380609015e70SStefano Zampini if (useCone) { 380709015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 380809015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 380909015e70SStefano Zampini } else { 381009015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 381109015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 381209015e70SStefano Zampini } 381309015e70SStefano Zampini } else { 381409015e70SStefano Zampini if (useCone) { 381509015e70SStefano Zampini const PetscSection s = mesh->coneSection; 381609015e70SStefano Zampini const PetscInt ps = p - s->pStart; 381709015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 381809015e70SStefano Zampini 381909015e70SStefano Zampini *size = s->atlasDof[ps]; 382009015e70SStefano Zampini *arr = mesh->cones + off; 382109015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 382209015e70SStefano Zampini } else { 382309015e70SStefano Zampini const PetscSection s = mesh->supportSection; 382409015e70SStefano Zampini const PetscInt ps = p - s->pStart; 382509015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 382609015e70SStefano Zampini 382709015e70SStefano Zampini *size = s->atlasDof[ps]; 382809015e70SStefano Zampini *arr = mesh->supports + off; 382909015e70SStefano Zampini } 383009015e70SStefano Zampini } 383109015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 383209015e70SStefano Zampini } 383309015e70SStefano Zampini 383409015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 383509015e70SStefano Zampini { 383609015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 383709015e70SStefano Zampini 383809015e70SStefano Zampini PetscFunctionBeginHot; 383909015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 384009015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 384109015e70SStefano Zampini } 384209015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 384309015e70SStefano Zampini } 384409015e70SStefano Zampini 3845d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3846d71ae5a4SJacob Faibussowitsch { 3847b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3848b5a892a1SMatthew G. Knepley PetscInt *closure; 3849b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3850b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3851b5a892a1SMatthew G. Knepley 3852b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3853b5a892a1SMatthew G. Knepley if (ornt) { 38549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3855476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3856b5a892a1SMatthew G. Knepley } 3857b5a892a1SMatthew G. Knepley if (*points) { 3858b5a892a1SMatthew G. Knepley closure = *points; 3859b5a892a1SMatthew G. Knepley } else { 3860b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38619566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3863b5a892a1SMatthew G. Knepley } 386409015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3865b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3866b5a892a1SMatthew G. Knepley closure[off++] = p; 3867b5a892a1SMatthew G. Knepley closure[off++] = 0; 3868b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3869b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3870b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3871b5a892a1SMatthew G. Knepley } 3872b5a892a1SMatthew G. Knepley } else { 387385036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3874b5a892a1SMatthew G. Knepley 3875b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3876b5a892a1SMatthew G. Knepley closure[off++] = p; 3877b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3878b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3879b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3880b5a892a1SMatthew G. Knepley 38819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3882b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3883b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3884b5a892a1SMatthew G. Knepley } 3885b5a892a1SMatthew G. Knepley } 388609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3887b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3888b5a892a1SMatthew G. Knepley if (points) *points = closure; 38893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3890b5a892a1SMatthew G. Knepley } 3891b5a892a1SMatthew G. Knepley 3892d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3893d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3894d71ae5a4SJacob Faibussowitsch { 389585036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3896b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3897b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3898b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3899b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3900b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3901b5a892a1SMatthew G. Knepley 3902b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 390409015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 39059566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3906b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3907b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3908b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39099371c9d4SSatish Balay if (*points) { 39109371c9d4SSatish Balay pts = *points; 39119371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3912b5a892a1SMatthew G. Knepley c = 0; 3913b5a892a1SMatthew G. Knepley pts[c++] = point; 3914b5a892a1SMatthew G. Knepley pts[c++] = o; 39159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 39169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 39179371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39189371c9d4SSatish Balay pts[c++] = closure[cl]; 39199371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39209371c9d4SSatish Balay } 39219566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 39229371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 39239371c9d4SSatish Balay pts[c++] = closure[cl]; 39249371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 39259371c9d4SSatish Balay } 39269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3927b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 39289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3929b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3930b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3931b5a892a1SMatthew G. Knepley } 393209015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3933b5a892a1SMatthew G. Knepley if (dim >= 3) { 3934b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3935b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3936b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3937b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3938b5a892a1SMatthew G. Knepley 39399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 394085036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 394109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3942b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3943b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3944b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3945b5a892a1SMatthew G. Knepley 39469371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39479371c9d4SSatish Balay if (pts[i] == cp) break; 3948b5a892a1SMatthew G. Knepley if (i == c) { 39499566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3950b5a892a1SMatthew G. Knepley pts[c++] = cp; 3951b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3952b5a892a1SMatthew G. Knepley } 3953b5a892a1SMatthew G. Knepley } 395409015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3955b5a892a1SMatthew G. Knepley } 3956b5a892a1SMatthew G. Knepley } 3957b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3958b5a892a1SMatthew G. Knepley *points = pts; 39593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3960b5a892a1SMatthew G. Knepley } 3961b5a892a1SMatthew G. Knepley 3962d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3963d71ae5a4SJacob Faibussowitsch { 3964b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3965b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3966b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3967b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3968b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3969b5a892a1SMatthew G. Knepley 3970b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39719566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3972b5a892a1SMatthew G. Knepley if (depth == 1) { 39739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3975b5a892a1SMatthew G. Knepley } 39769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3977476787b7SMatthew G. Knepley if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN || ct == DM_POLYTOPE_UNKNOWN_CELL || ct == DM_POLYTOPE_UNKNOWN_FACE) ct = DM_POLYTOPE_UNKNOWN; 3978c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39799566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3981b5a892a1SMatthew G. Knepley } 39829566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3983b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3984b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3985b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39879371c9d4SSatish Balay if (*points) { 39889371c9d4SSatish Balay closure = *points; 39899371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3990b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3991b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3992b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3993b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3994b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3995b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3996b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3997b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3998b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3999b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 400085036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 400109015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4002b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4003b5a892a1SMatthew G. Knepley 4004b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 400585036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 400663a3b9bcSJacob Faibussowitsch PetscCheck(!o || !(o >= nO || o < -nO), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q); 4007b5a892a1SMatthew G. Knepley } 400809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4009b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4010b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4011b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4012b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 40139566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4014b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4015b5a892a1SMatthew G. Knepley PetscInt c; 4016b5a892a1SMatthew G. Knepley 4017b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4018b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4019b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4020b5a892a1SMatthew G. Knepley } 4021b5a892a1SMatthew G. Knepley if (c == closureSize) { 4022b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4023b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4024b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4025b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4026b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4027b5a892a1SMatthew G. Knepley } 4028b5a892a1SMatthew G. Knepley } 402909015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4030b5a892a1SMatthew G. Knepley } 40319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4032b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4033b5a892a1SMatthew G. Knepley if (points) *points = closure; 40343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4035b5a892a1SMatthew G. Knepley } 4036b5a892a1SMatthew G. Knepley 4037552f7358SJed Brown /*@C 4038eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4039552f7358SJed Brown 4040a1cb98faSBarry Smith Not Collective 4041552f7358SJed Brown 4042552f7358SJed Brown Input Parameters: 4043a1cb98faSBarry Smith + dm - The `DMPLEX` 4044b5a892a1SMatthew G. Knepley . p - The mesh point 4045a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4046552f7358SJed Brown 40476b867d5aSJose E. Roman Input/Output Parameter: 40486b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 404920f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40506b867d5aSJose E. Roman 40516b867d5aSJose E. Roman Output Parameter: 405220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4053552f7358SJed Brown 4054a1cb98faSBarry Smith Level: beginner 4055a1cb98faSBarry Smith 4056552f7358SJed Brown Note: 405720f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4058552f7358SJed Brown 405960225df5SJacob Faibussowitsch Fortran Notes: 406020f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40613813dfbdSMatthew G Knepley 40621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4063552f7358SJed Brown @*/ 4064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4065d71ae5a4SJacob Faibussowitsch { 4066b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4067552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40684f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40694f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40729bf0dad6SMatthew G. Knepley } 40739bf0dad6SMatthew G. Knepley 4074552f7358SJed Brown /*@C 4075eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4076552f7358SJed Brown 4077a1cb98faSBarry Smith Not Collective 4078552f7358SJed Brown 4079552f7358SJed Brown Input Parameters: 4080a1cb98faSBarry Smith + dm - The `DMPLEX` 4081b5a892a1SMatthew G. Knepley . p - The mesh point 4082a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 408320f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4084b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4085552f7358SJed Brown 4086a1cb98faSBarry Smith Level: beginner 4087a1cb98faSBarry Smith 4088552f7358SJed Brown Note: 408920f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4090552f7358SJed Brown 40911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4092552f7358SJed Brown @*/ 4093d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4094d71ae5a4SJacob Faibussowitsch { 4095b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4096552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40974ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40989566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 40993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4100552f7358SJed Brown } 4101552f7358SJed Brown 4102552f7358SJed Brown /*@ 4103eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4104552f7358SJed Brown 4105a1cb98faSBarry Smith Not Collective 4106552f7358SJed Brown 4107552f7358SJed Brown Input Parameter: 410860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4109552f7358SJed Brown 4110552f7358SJed Brown Output Parameters: 4111552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4112552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4113552f7358SJed Brown 4114552f7358SJed Brown Level: beginner 4115552f7358SJed Brown 41161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4117552f7358SJed Brown @*/ 4118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4119d71ae5a4SJacob Faibussowitsch { 4120552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4121552f7358SJed Brown 4122552f7358SJed Brown PetscFunctionBegin; 4123552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41241baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 41251baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 41263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4127552f7358SJed Brown } 4128552f7358SJed Brown 4129d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4130d71ae5a4SJacob Faibussowitsch { 4131552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 41326302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4133552f7358SJed Brown 4134552f7358SJed Brown PetscFunctionBegin; 4135552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41406302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41416302a7fbSVaclav Hapla if (maxSupportSize) { 41429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4145552f7358SJed Brown } 41463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4147552f7358SJed Brown } 4148552f7358SJed Brown 4149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4150d71ae5a4SJacob Faibussowitsch { 4151552f7358SJed Brown PetscFunctionBegin; 41529566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4153dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4154ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4155736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 415695602cf2SAlexis Marboeuf PetscSF sfNatural; 4157f94b4a02SBlaise Bourdin 41583dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 416095602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4161c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4162f94b4a02SBlaise Bourdin } 41633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4164552f7358SJed Brown } 4165552f7358SJed Brown 4166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4167d71ae5a4SJacob Faibussowitsch { 41683dcd263cSBlaise Bourdin PetscInt i = 0; 41692adcc780SMatthew G. Knepley 41702adcc780SMatthew G. Knepley PetscFunctionBegin; 41719566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41729566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4173c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41743dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41753dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 417695602cf2SAlexis Marboeuf PetscSF sfNatural; 41773dcd263cSBlaise Bourdin 41783dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4180c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 418195602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4182c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41833dcd263cSBlaise Bourdin break; 41843dcd263cSBlaise Bourdin } 41853dcd263cSBlaise Bourdin } 41863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41872adcc780SMatthew G. Knepley } 41882adcc780SMatthew G. Knepley 4189552f7358SJed Brown /*@ 4190eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4191552f7358SJed Brown 4192a1cb98faSBarry Smith Not Collective 4193552f7358SJed Brown 4194552f7358SJed Brown Input Parameter: 419560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4196552f7358SJed Brown 4197552f7358SJed Brown Level: beginner 4198552f7358SJed Brown 4199a1cb98faSBarry Smith Note: 4200a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4201a1cb98faSBarry Smith 42021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4203552f7358SJed Brown @*/ 4204d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4205d71ae5a4SJacob Faibussowitsch { 4206552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4207552f7358SJed Brown PetscInt *offsets; 4208552f7358SJed Brown PetscInt supportSize; 4209552f7358SJed Brown PetscInt pStart, pEnd, p; 4210552f7358SJed Brown 4211552f7358SJed Brown PetscFunctionBegin; 4212552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 421328b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 42149566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4215552f7358SJed Brown /* Calculate support sizes */ 42169566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4217552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4218552f7358SJed Brown PetscInt dof, off, c; 4219552f7358SJed Brown 42209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 422248a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4223552f7358SJed Brown } 42249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4225552f7358SJed Brown /* Calculate supports */ 42269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 42279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 42289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4229552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4230552f7358SJed Brown PetscInt dof, off, c; 4231552f7358SJed Brown 42329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4234552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4235552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4236552f7358SJed Brown PetscInt offS; 4237552f7358SJed Brown 42389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42390d644c17SKarl Rupp 4240552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4241552f7358SJed Brown ++offsets[q]; 4242552f7358SJed Brown } 4243552f7358SJed Brown } 42449566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4247552f7358SJed Brown } 4248552f7358SJed Brown 4249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4250d71ae5a4SJacob Faibussowitsch { 4251277ea44aSLisandro Dalcin IS stratumIS; 4252277ea44aSLisandro Dalcin 4253277ea44aSLisandro Dalcin PetscFunctionBegin; 42543ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 425576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4256277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4257277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42589566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4259277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42609566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42619371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42629371c9d4SSatish Balay overlap = PETSC_TRUE; 42639371c9d4SSatish Balay break; 42649371c9d4SSatish Balay } 4265277ea44aSLisandro Dalcin } 426663a3b9bcSJacob Faibussowitsch PetscCheck(!overlap, PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd); 4267277ea44aSLisandro Dalcin } 42689566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42699566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4272277ea44aSLisandro Dalcin } 4273277ea44aSLisandro Dalcin 4274e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4275e91fa0a1SMatthew G. Knepley { 4276e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4277e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4278e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4279e91fa0a1SMatthew G. Knepley 4280e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4281e91fa0a1SMatthew G. Knepley { 4282e91fa0a1SMatthew G. Knepley DMLabel label2; 4283e91fa0a1SMatthew G. Knepley 4284e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4285e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4286e91fa0a1SMatthew G. Knepley } 4287e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4288e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4289e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4290e91fa0a1SMatthew G. Knepley 4291e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4292e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4293e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4294e91fa0a1SMatthew G. Knepley } 4295e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4296e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4297e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4298e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4299e91fa0a1SMatthew G. Knepley } 4300e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4301e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4302e91fa0a1SMatthew G. Knepley PetscInt d; 4303e91fa0a1SMatthew G. Knepley 4304e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4305e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4306e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4307e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4308e91fa0a1SMatthew G. Knepley } 4309e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4310e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4311e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4312e91fa0a1SMatthew G. Knepley } 4313e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4314e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4315e91fa0a1SMatthew G. Knepley } 4316e91fa0a1SMatthew G. Knepley 4317e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4318e91fa0a1SMatthew G. Knepley { 4319e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4320e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4321e91fa0a1SMatthew G. Knepley 4322e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4323e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4324e91fa0a1SMatthew G. Knepley { 4325e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4326e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4327e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4328e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4329e91fa0a1SMatthew G. Knepley 4330e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4331e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4332e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4333e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4334e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4335e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4336e91fa0a1SMatthew G. Knepley ++numRoots; 4337e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4338e91fa0a1SMatthew G. Knepley ++numLeaves; 4339e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4340e91fa0a1SMatthew G. Knepley /* Isolated points */ 4341e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4342e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4343e91fa0a1SMatthew G. Knepley } 4344e91fa0a1SMatthew G. Knepley } 4345e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4346e91fa0a1SMatthew G. Knepley } 4347e91fa0a1SMatthew G. Knepley 4348e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4349e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4350e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4351e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4352e91fa0a1SMatthew G. Knepley 4353e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4354e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4355e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4356e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4357e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4358e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4359e91fa0a1SMatthew G. Knepley } 4360e91fa0a1SMatthew G. Knepley } 4361e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4362e91fa0a1SMatthew G. Knepley } else { 4363e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4364e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4365e91fa0a1SMatthew G. Knepley 4366e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4367e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4368e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4369e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4370e91fa0a1SMatthew G. Knepley 4371e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4372e91fa0a1SMatthew G. Knepley const PetscInt *support; 4373e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4374e91fa0a1SMatthew G. Knepley 4375e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4376e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4377e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4378e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4379e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4380e91fa0a1SMatthew G. Knepley } 4381e91fa0a1SMatthew G. Knepley } 4382e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4383e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4384e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4385e91fa0a1SMatthew G. Knepley } 4386e91fa0a1SMatthew G. Knepley } 4387e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4388e91fa0a1SMatthew G. Knepley } 4389e91fa0a1SMatthew G. Knepley 4390552f7358SJed Brown /*@ 4391a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4392552f7358SJed Brown 439320f4b53cSBarry Smith Collective 4394552f7358SJed Brown 4395552f7358SJed Brown Input Parameter: 439660225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4397552f7358SJed Brown 4398a1cb98faSBarry Smith Level: beginner 4399552f7358SJed Brown 4400552f7358SJed Brown Notes: 4401a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4402a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4403a4e35b19SJacob Faibussowitsch 4404a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4405a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4406a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4407b1bb481bSMatthew Knepley meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on 4408a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4409a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4410a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4411552f7358SJed Brown 4412b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4413b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4414b1bb481bSMatthew Knepley we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose 4415b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4416a1cb98faSBarry Smith .vb 4417a1cb98faSBarry Smith cone(c0) = {e0, v2} 4418a1cb98faSBarry Smith cone(e0) = {v0, v1} 4419a1cb98faSBarry Smith .ve 4420a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4421a1cb98faSBarry Smith .vb 4422a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4423a1cb98faSBarry Smith depth 1 = {e0, c0} 4424a1cb98faSBarry Smith .ve 4425b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4426b1bb481bSMatthew Knepley 4427a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4428552f7358SJed Brown 44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4430552f7358SJed Brown @*/ 4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4432d71ae5a4SJacob Faibussowitsch { 4433df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4434aa50250dSMatthew G. Knepley DMLabel label; 4435e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4436552f7358SJed Brown 4437552f7358SJed Brown PetscFunctionBegin; 4438552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4440277ea44aSLisandro Dalcin 4441e91fa0a1SMatthew G. Knepley // Create depth label 44429566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4444277ea44aSLisandro Dalcin 4445e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4446e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4447e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4448552f7358SJed Brown 4449bf4602e4SToby Isaac { /* just in case there is an empty process */ 4450bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4451bf4602e4SToby Isaac 44529566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4453712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 445448a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4455bf4602e4SToby Isaac } 44569566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4459552f7358SJed Brown } 4460552f7358SJed Brown 4461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4462d71ae5a4SJacob Faibussowitsch { 4463412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4464412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4465ba2698f1SMatthew G. Knepley 4466412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44679566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4470ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4471ba2698f1SMatthew G. Knepley if (depth <= 1) { 4472ba2698f1SMatthew G. Knepley switch (pdepth) { 4473d71ae5a4SJacob Faibussowitsch case 0: 4474d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4475d71ae5a4SJacob Faibussowitsch break; 4476ba2698f1SMatthew G. Knepley case 1: 4477ba2698f1SMatthew G. Knepley switch (coneSize) { 4478d71ae5a4SJacob Faibussowitsch case 2: 4479d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4480d71ae5a4SJacob Faibussowitsch break; 4481d71ae5a4SJacob Faibussowitsch case 3: 4482d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4483d71ae5a4SJacob Faibussowitsch break; 4484ba2698f1SMatthew G. Knepley case 4: 4485ba2698f1SMatthew G. Knepley switch (dim) { 4486d71ae5a4SJacob Faibussowitsch case 2: 4487d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4488d71ae5a4SJacob Faibussowitsch break; 4489d71ae5a4SJacob Faibussowitsch case 3: 4490d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4491d71ae5a4SJacob Faibussowitsch break; 4492d71ae5a4SJacob Faibussowitsch default: 4493d71ae5a4SJacob Faibussowitsch break; 4494ba2698f1SMatthew G. Knepley } 4495ba2698f1SMatthew G. Knepley break; 4496d71ae5a4SJacob Faibussowitsch case 5: 4497d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4498d71ae5a4SJacob Faibussowitsch break; 4499d71ae5a4SJacob Faibussowitsch case 6: 4500d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4501d71ae5a4SJacob Faibussowitsch break; 4502d71ae5a4SJacob Faibussowitsch case 8: 4503d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4504d71ae5a4SJacob Faibussowitsch break; 4505d71ae5a4SJacob Faibussowitsch default: 4506d71ae5a4SJacob Faibussowitsch break; 4507ba2698f1SMatthew G. Knepley } 4508ba2698f1SMatthew G. Knepley } 4509ba2698f1SMatthew G. Knepley } else { 4510ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4511ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4512ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4513ba2698f1SMatthew G. Knepley switch (dim) { 4514ba2698f1SMatthew G. Knepley case 1: 4515ba2698f1SMatthew G. Knepley switch (coneSize) { 4516d71ae5a4SJacob Faibussowitsch case 2: 4517d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4518d71ae5a4SJacob Faibussowitsch break; 4519d71ae5a4SJacob Faibussowitsch default: 4520d71ae5a4SJacob Faibussowitsch break; 4521ba2698f1SMatthew G. Knepley } 4522ba2698f1SMatthew G. Knepley break; 4523ba2698f1SMatthew G. Knepley case 2: 4524ba2698f1SMatthew G. Knepley switch (coneSize) { 4525d71ae5a4SJacob Faibussowitsch case 3: 4526d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4527d71ae5a4SJacob Faibussowitsch break; 4528d71ae5a4SJacob Faibussowitsch case 4: 4529d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4530d71ae5a4SJacob Faibussowitsch break; 4531d71ae5a4SJacob Faibussowitsch default: 4532d71ae5a4SJacob Faibussowitsch break; 4533ba2698f1SMatthew G. Knepley } 4534ba2698f1SMatthew G. Knepley break; 4535ba2698f1SMatthew G. Knepley case 3: 4536ba2698f1SMatthew G. Knepley switch (coneSize) { 4537d71ae5a4SJacob Faibussowitsch case 4: 4538d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4539d71ae5a4SJacob Faibussowitsch break; 45409371c9d4SSatish Balay case 5: { 4541da9060c4SMatthew G. Knepley const PetscInt *cone; 4542da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4543da9060c4SMatthew G. Knepley 45449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45459566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4546da9060c4SMatthew G. Knepley switch (faceConeSize) { 4547d71ae5a4SJacob Faibussowitsch case 3: 4548d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4549d71ae5a4SJacob Faibussowitsch break; 4550d71ae5a4SJacob Faibussowitsch case 4: 4551d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4552d71ae5a4SJacob Faibussowitsch break; 4553da9060c4SMatthew G. Knepley } 45549371c9d4SSatish Balay } break; 4555d71ae5a4SJacob Faibussowitsch case 6: 4556d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4557d71ae5a4SJacob Faibussowitsch break; 4558d71ae5a4SJacob Faibussowitsch default: 4559d71ae5a4SJacob Faibussowitsch break; 4560ba2698f1SMatthew G. Knepley } 4561ba2698f1SMatthew G. Knepley break; 4562d71ae5a4SJacob Faibussowitsch default: 4563d71ae5a4SJacob Faibussowitsch break; 4564ba2698f1SMatthew G. Knepley } 4565ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4566ba2698f1SMatthew G. Knepley switch (coneSize) { 4567d71ae5a4SJacob Faibussowitsch case 2: 4568d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4569d71ae5a4SJacob Faibussowitsch break; 4570d71ae5a4SJacob Faibussowitsch case 3: 4571d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4572d71ae5a4SJacob Faibussowitsch break; 4573d71ae5a4SJacob Faibussowitsch case 4: 4574d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4575d71ae5a4SJacob Faibussowitsch break; 4576d71ae5a4SJacob Faibussowitsch default: 4577d71ae5a4SJacob Faibussowitsch break; 4578ba2698f1SMatthew G. Knepley } 4579ba2698f1SMatthew G. Knepley } 4580ba2698f1SMatthew G. Knepley } 4581412e9a14SMatthew G. Knepley *pt = ct; 45823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4583ba2698f1SMatthew G. Knepley } 4584412e9a14SMatthew G. Knepley 4585412e9a14SMatthew G. Knepley /*@ 4586412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4587412e9a14SMatthew G. Knepley 458820f4b53cSBarry Smith Collective 4589412e9a14SMatthew G. Knepley 4590412e9a14SMatthew G. Knepley Input Parameter: 459160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4592412e9a14SMatthew G. Knepley 4593412e9a14SMatthew G. Knepley Level: developer 4594412e9a14SMatthew G. Knepley 4595a1cb98faSBarry Smith Note: 4596a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4597a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4598a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4599412e9a14SMatthew G. Knepley 4600a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4601a1cb98faSBarry Smith 46021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4603412e9a14SMatthew G. Knepley @*/ 4604d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4605d71ae5a4SJacob Faibussowitsch { 4606412e9a14SMatthew G. Knepley DM_Plex *mesh; 4607412e9a14SMatthew G. Knepley DMLabel ctLabel; 4608412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4609412e9a14SMatthew G. Knepley 4610412e9a14SMatthew G. Knepley PetscFunctionBegin; 4611412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4612412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 46139566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 46149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 46159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 461621027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 461721027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4618412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4619327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4620412e9a14SMatthew G. Knepley PetscInt pdepth; 4621412e9a14SMatthew G. Knepley 46229566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 46239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4624476787b7SMatthew 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); 46259566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 462621027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4627412e9a14SMatthew G. Knepley } 46289566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 46299566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 46303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4631ba2698f1SMatthew G. Knepley } 4632ba2698f1SMatthew G. Knepley 4633552f7358SJed Brown /*@C 4634552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4635552f7358SJed Brown 4636552f7358SJed Brown Not Collective 4637552f7358SJed Brown 4638552f7358SJed Brown Input Parameters: 4639a1cb98faSBarry Smith + dm - The `DMPLEX` object 4640552f7358SJed Brown . numPoints - The number of input points for the join 4641552f7358SJed Brown - points - The input points 4642552f7358SJed Brown 4643552f7358SJed Brown Output Parameters: 4644552f7358SJed Brown + numCoveredPoints - The number of points in the join 4645552f7358SJed Brown - coveredPoints - The points in the join 4646552f7358SJed Brown 4647552f7358SJed Brown Level: intermediate 4648552f7358SJed Brown 4649a1cb98faSBarry Smith Note: 4650a1cb98faSBarry Smith Currently, this is restricted to a single level join 4651552f7358SJed Brown 465260225df5SJacob Faibussowitsch Fortran Notes: 465320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46543813dfbdSMatthew G Knepley 46551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4656552f7358SJed Brown @*/ 4657d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4658d71ae5a4SJacob Faibussowitsch { 4659552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4660552f7358SJed Brown PetscInt *join[2]; 4661552f7358SJed Brown PetscInt joinSize, i = 0; 4662552f7358SJed Brown PetscInt dof, off, p, c, m; 46636302a7fbSVaclav Hapla PetscInt maxSupportSize; 4664552f7358SJed Brown 4665552f7358SJed Brown PetscFunctionBegin; 4666552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46674f572ea9SToby Isaac PetscAssertPointer(points, 3); 46684f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46694f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46706302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46716302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46726302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4673552f7358SJed Brown /* Copy in support of first point */ 46749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4676ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4677552f7358SJed Brown /* Check each successive support */ 4678552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4679552f7358SJed Brown PetscInt newJoinSize = 0; 4680552f7358SJed Brown 46819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4683552f7358SJed Brown for (c = 0; c < dof; ++c) { 4684552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4685552f7358SJed Brown 4686552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4687552f7358SJed Brown if (point == join[i][m]) { 4688552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4689552f7358SJed Brown break; 4690552f7358SJed Brown } 4691552f7358SJed Brown } 4692552f7358SJed Brown } 4693552f7358SJed Brown joinSize = newJoinSize; 4694552f7358SJed Brown i = 1 - i; 4695552f7358SJed Brown } 4696552f7358SJed Brown *numCoveredPoints = joinSize; 4697552f7358SJed Brown *coveredPoints = join[i]; 46986302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 46993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4700552f7358SJed Brown } 4701552f7358SJed Brown 4702552f7358SJed Brown /*@C 4703552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4704552f7358SJed Brown 4705552f7358SJed Brown Not Collective 4706552f7358SJed Brown 4707552f7358SJed Brown Input Parameters: 4708a1cb98faSBarry Smith + dm - The `DMPLEX` object 4709552f7358SJed Brown . numPoints - The number of input points for the join 4710552f7358SJed Brown - points - The input points 4711552f7358SJed Brown 4712552f7358SJed Brown Output Parameters: 4713552f7358SJed Brown + numCoveredPoints - The number of points in the join 4714552f7358SJed Brown - coveredPoints - The points in the join 4715552f7358SJed Brown 4716552f7358SJed Brown Level: intermediate 4717552f7358SJed Brown 471860225df5SJacob Faibussowitsch Fortran Notes: 471920f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4720a1cb98faSBarry Smith 47211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4722552f7358SJed Brown @*/ 4723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4724d71ae5a4SJacob Faibussowitsch { 4725552f7358SJed Brown PetscFunctionBegin; 4726552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47274f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 47284f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 47294f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4731d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 47323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4733552f7358SJed Brown } 4734552f7358SJed Brown 4735552f7358SJed Brown /*@C 4736552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4737552f7358SJed Brown 4738552f7358SJed Brown Not Collective 4739552f7358SJed Brown 4740552f7358SJed Brown Input Parameters: 4741a1cb98faSBarry Smith + dm - The `DMPLEX` object 4742552f7358SJed Brown . numPoints - The number of input points for the join 4743552f7358SJed Brown - points - The input points 4744552f7358SJed Brown 4745552f7358SJed Brown Output Parameters: 4746552f7358SJed Brown + numCoveredPoints - The number of points in the join 4747552f7358SJed Brown - coveredPoints - The points in the join 4748552f7358SJed Brown 4749552f7358SJed Brown Level: intermediate 4750552f7358SJed Brown 475160225df5SJacob Faibussowitsch Fortran Notes: 475220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4753a1cb98faSBarry Smith 47541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4755552f7358SJed Brown @*/ 4756d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4757d71ae5a4SJacob Faibussowitsch { 4758552f7358SJed Brown PetscInt *offsets, **closures; 4759552f7358SJed Brown PetscInt *join[2]; 4760552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 476124c766afSToby Isaac PetscInt p, d, c, m, ms; 4762552f7358SJed Brown 4763552f7358SJed Brown PetscFunctionBegin; 4764552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47654f572ea9SToby Isaac PetscAssertPointer(points, 3); 47664f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47674f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4768552f7358SJed Brown 47699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47719566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47726302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 477324c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47759566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4776552f7358SJed Brown 4777552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4778552f7358SJed Brown PetscInt closureSize; 4779552f7358SJed Brown 47809566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47810d644c17SKarl Rupp 4782552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4783552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4784552f7358SJed Brown PetscInt pStart, pEnd, i; 4785552f7358SJed Brown 47869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4787552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4788552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4789552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4790552f7358SJed Brown break; 4791552f7358SJed Brown } 4792552f7358SJed Brown } 4793552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4794552f7358SJed Brown } 479563a3b9bcSJacob 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); 4796552f7358SJed Brown } 4797552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4798552f7358SJed Brown PetscInt dof; 4799552f7358SJed Brown 4800552f7358SJed Brown /* Copy in support of first point */ 4801552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4802ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4803552f7358SJed Brown /* Check each successive cone */ 4804552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4805552f7358SJed Brown PetscInt newJoinSize = 0; 4806552f7358SJed Brown 4807552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4808552f7358SJed Brown for (c = 0; c < dof; ++c) { 4809552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4810552f7358SJed Brown 4811552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4812552f7358SJed Brown if (point == join[i][m]) { 4813552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4814552f7358SJed Brown break; 4815552f7358SJed Brown } 4816552f7358SJed Brown } 4817552f7358SJed Brown } 4818552f7358SJed Brown joinSize = newJoinSize; 4819552f7358SJed Brown i = 1 - i; 4820552f7358SJed Brown } 4821552f7358SJed Brown if (joinSize) break; 4822552f7358SJed Brown } 4823552f7358SJed Brown *numCoveredPoints = joinSize; 4824552f7358SJed Brown *coveredPoints = join[i]; 482548a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 48269566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 48279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48286302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 48293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4830552f7358SJed Brown } 4831552f7358SJed Brown 4832552f7358SJed Brown /*@C 4833552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4834552f7358SJed Brown 4835552f7358SJed Brown Not Collective 4836552f7358SJed Brown 4837552f7358SJed Brown Input Parameters: 4838a1cb98faSBarry Smith + dm - The `DMPLEX` object 4839552f7358SJed Brown . numPoints - The number of input points for the meet 4840552f7358SJed Brown - points - The input points 4841552f7358SJed Brown 4842552f7358SJed Brown Output Parameters: 484360225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 484460225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4845552f7358SJed Brown 4846552f7358SJed Brown Level: intermediate 4847552f7358SJed Brown 4848a1cb98faSBarry Smith Note: 4849a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4850552f7358SJed Brown 48513813dfbdSMatthew G Knepley Fortran Notes: 485220f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48533813dfbdSMatthew G Knepley 48541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4855552f7358SJed Brown @*/ 4856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4857d71ae5a4SJacob Faibussowitsch { 4858552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4859552f7358SJed Brown PetscInt *meet[2]; 4860552f7358SJed Brown PetscInt meetSize, i = 0; 4861552f7358SJed Brown PetscInt dof, off, p, c, m; 48626302a7fbSVaclav Hapla PetscInt maxConeSize; 4863552f7358SJed Brown 4864552f7358SJed Brown PetscFunctionBegin; 4865552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48664f572ea9SToby Isaac PetscAssertPointer(points, 3); 48674f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48684f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48696302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48706302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48716302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4872552f7358SJed Brown /* Copy in cone of first point */ 48739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4875ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4876552f7358SJed Brown /* Check each successive cone */ 4877552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4878552f7358SJed Brown PetscInt newMeetSize = 0; 4879552f7358SJed Brown 48809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4882552f7358SJed Brown for (c = 0; c < dof; ++c) { 4883552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4884552f7358SJed Brown 4885552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4886552f7358SJed Brown if (point == meet[i][m]) { 4887552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4888552f7358SJed Brown break; 4889552f7358SJed Brown } 4890552f7358SJed Brown } 4891552f7358SJed Brown } 4892552f7358SJed Brown meetSize = newMeetSize; 4893552f7358SJed Brown i = 1 - i; 4894552f7358SJed Brown } 4895552f7358SJed Brown *numCoveringPoints = meetSize; 4896552f7358SJed Brown *coveringPoints = meet[i]; 48976302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4899552f7358SJed Brown } 4900552f7358SJed Brown 4901552f7358SJed Brown /*@C 4902552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4903552f7358SJed Brown 4904552f7358SJed Brown Not Collective 4905552f7358SJed Brown 4906552f7358SJed Brown Input Parameters: 4907a1cb98faSBarry Smith + dm - The `DMPLEX` object 4908552f7358SJed Brown . numPoints - The number of input points for the meet 4909552f7358SJed Brown - points - The input points 4910552f7358SJed Brown 4911552f7358SJed Brown Output Parameters: 4912552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4913552f7358SJed Brown - coveredPoints - The points in the meet 4914552f7358SJed Brown 4915552f7358SJed Brown Level: intermediate 4916552f7358SJed Brown 491760225df5SJacob Faibussowitsch Fortran Notes: 491820f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49193813dfbdSMatthew G Knepley 49201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4921552f7358SJed Brown @*/ 4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4923d71ae5a4SJacob Faibussowitsch { 4924552f7358SJed Brown PetscFunctionBegin; 4925552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49264f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 49274f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 49284f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 49299566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4930d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 49313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4932552f7358SJed Brown } 4933552f7358SJed Brown 4934552f7358SJed Brown /*@C 4935552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 4936552f7358SJed Brown 4937552f7358SJed Brown Not Collective 4938552f7358SJed Brown 4939552f7358SJed Brown Input Parameters: 4940a1cb98faSBarry Smith + dm - The `DMPLEX` object 4941552f7358SJed Brown . numPoints - The number of input points for the meet 4942552f7358SJed Brown - points - The input points 4943552f7358SJed Brown 4944552f7358SJed Brown Output Parameters: 4945552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4946552f7358SJed Brown - coveredPoints - The points in the meet 4947552f7358SJed Brown 4948552f7358SJed Brown Level: intermediate 4949552f7358SJed Brown 495060225df5SJacob Faibussowitsch Fortran Notes: 495120f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49523813dfbdSMatthew G Knepley 49531cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4954552f7358SJed Brown @*/ 4955d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4956d71ae5a4SJacob Faibussowitsch { 4957552f7358SJed Brown PetscInt *offsets, **closures; 4958552f7358SJed Brown PetscInt *meet[2]; 4959552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 496024c766afSToby Isaac PetscInt p, h, c, m, mc; 4961552f7358SJed Brown 4962552f7358SJed Brown PetscFunctionBegin; 4963552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49644f572ea9SToby Isaac PetscAssertPointer(points, 3); 49654f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49664f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4967552f7358SJed Brown 49689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49716302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 497224c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4975552f7358SJed Brown 4976552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4977552f7358SJed Brown PetscInt closureSize; 4978552f7358SJed Brown 49799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49800d644c17SKarl Rupp 4981552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4982552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4983552f7358SJed Brown PetscInt pStart, pEnd, i; 4984552f7358SJed Brown 49859566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4986552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4987552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4988552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4989552f7358SJed Brown break; 4990552f7358SJed Brown } 4991552f7358SJed Brown } 4992552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4993552f7358SJed Brown } 499463a3b9bcSJacob 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); 4995552f7358SJed Brown } 4996552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4997552f7358SJed Brown PetscInt dof; 4998552f7358SJed Brown 4999552f7358SJed Brown /* Copy in cone of first point */ 5000552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5001ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5002552f7358SJed Brown /* Check each successive cone */ 5003552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5004552f7358SJed Brown PetscInt newMeetSize = 0; 5005552f7358SJed Brown 5006552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5007552f7358SJed Brown for (c = 0; c < dof; ++c) { 5008552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5009552f7358SJed Brown 5010552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5011552f7358SJed Brown if (point == meet[i][m]) { 5012552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5013552f7358SJed Brown break; 5014552f7358SJed Brown } 5015552f7358SJed Brown } 5016552f7358SJed Brown } 5017552f7358SJed Brown meetSize = newMeetSize; 5018552f7358SJed Brown i = 1 - i; 5019552f7358SJed Brown } 5020552f7358SJed Brown if (meetSize) break; 5021552f7358SJed Brown } 5022552f7358SJed Brown *numCoveredPoints = meetSize; 5023552f7358SJed Brown *coveredPoints = meet[i]; 502448a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 50259566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 50269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50276302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 50283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5029552f7358SJed Brown } 5030552f7358SJed Brown 50314e3744c5SMatthew G. Knepley /*@C 5032a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50334e3744c5SMatthew G. Knepley 50344e3744c5SMatthew G. Knepley Not Collective 50354e3744c5SMatthew G. Knepley 50364e3744c5SMatthew G. Knepley Input Parameters: 5037a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5038a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50394e3744c5SMatthew G. Knepley 50402fe279fdSBarry Smith Output Parameter: 5041a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50424e3744c5SMatthew G. Knepley 50434e3744c5SMatthew G. Knepley Level: intermediate 50444e3744c5SMatthew G. Knepley 5045a1cb98faSBarry Smith Note: 50463c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50474e3744c5SMatthew G. Knepley 50481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50494e3744c5SMatthew G. Knepley @*/ 5050d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5051d71ae5a4SJacob Faibussowitsch { 50524e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50534e3744c5SMatthew G. Knepley 50544e3744c5SMatthew G. Knepley PetscFunctionBegin; 50554e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50564e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50574f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50584e3744c5SMatthew G. Knepley 50594e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50623ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50639566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50649566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50653ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50664e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50674e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50684e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50694e3744c5SMatthew G. Knepley 50709566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50763ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50774e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50783ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50793ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50804e3744c5SMatthew G. Knepley } 50819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50853ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50864e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50873ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50884e3744c5SMatthew G. Knepley } 50894e3744c5SMatthew G. Knepley } 50904e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50924e3744c5SMatthew G. Knepley } 50934e3744c5SMatthew G. Knepley 50947cd05799SMatthew G. Knepley /*@C 50957cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50967cd05799SMatthew G. Knepley 50977cd05799SMatthew G. Knepley Not Collective 50987cd05799SMatthew G. Knepley 50997cd05799SMatthew G. Knepley Input Parameters: 5100a1cb98faSBarry Smith + dm - The `DMPLEX` 51017cd05799SMatthew G. Knepley . cellDim - The cell dimension 51027cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 51037cd05799SMatthew G. Knepley 51042fe279fdSBarry Smith Output Parameter: 51057cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 51067cd05799SMatthew G. Knepley 51077cd05799SMatthew G. Knepley Level: developer 51087cd05799SMatthew G. Knepley 5109a1cb98faSBarry Smith Note: 51107cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 51117cd05799SMatthew G. Knepley 51121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51137cd05799SMatthew G. Knepley @*/ 5114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5115d71ae5a4SJacob Faibussowitsch { 511682f516ccSBarry Smith MPI_Comm comm; 5117552f7358SJed Brown 5118552f7358SJed Brown PetscFunctionBegin; 51199566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 51204f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5121552f7358SJed Brown switch (cellDim) { 5122d71ae5a4SJacob Faibussowitsch case 0: 5123d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5124d71ae5a4SJacob Faibussowitsch break; 5125d71ae5a4SJacob Faibussowitsch case 1: 5126d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5127d71ae5a4SJacob Faibussowitsch break; 5128552f7358SJed Brown case 2: 5129552f7358SJed Brown switch (numCorners) { 513019436ca2SJed Brown case 3: /* triangle */ 513119436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5132552f7358SJed Brown break; 513319436ca2SJed Brown case 4: /* quadrilateral */ 513419436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5135552f7358SJed Brown break; 513619436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 513719436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5138552f7358SJed Brown break; 513919436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 514019436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5141552f7358SJed Brown break; 5142d71ae5a4SJacob Faibussowitsch default: 5143d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5144552f7358SJed Brown } 5145552f7358SJed Brown break; 5146552f7358SJed Brown case 3: 5147552f7358SJed Brown switch (numCorners) { 514819436ca2SJed Brown case 4: /* tetradehdron */ 514919436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5150552f7358SJed Brown break; 515119436ca2SJed Brown case 6: /* tet cohesive cells */ 515219436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5153552f7358SJed Brown break; 515419436ca2SJed Brown case 8: /* hexahedron */ 515519436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5156552f7358SJed Brown break; 515719436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 515819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5159552f7358SJed Brown break; 516019436ca2SJed Brown case 10: /* quadratic tetrahedron */ 516119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5162552f7358SJed Brown break; 516319436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 516419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5165552f7358SJed Brown break; 516619436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 516719436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5168552f7358SJed Brown break; 516919436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 517019436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5171552f7358SJed Brown break; 5172d71ae5a4SJacob Faibussowitsch default: 5173d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5174552f7358SJed Brown } 5175552f7358SJed Brown break; 5176d71ae5a4SJacob Faibussowitsch default: 5177d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5178552f7358SJed Brown } 51793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5180552f7358SJed Brown } 5181552f7358SJed Brown 5182552f7358SJed Brown /*@ 5183a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5184552f7358SJed Brown 5185552f7358SJed Brown Not Collective 5186552f7358SJed Brown 5187aa50250dSMatthew G. Knepley Input Parameter: 5188a1cb98faSBarry Smith . dm - The `DMPLEX` object 5189552f7358SJed Brown 5190aa50250dSMatthew G. Knepley Output Parameter: 5191a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5192552f7358SJed Brown 5193552f7358SJed Brown Level: developer 5194552f7358SJed Brown 51951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5196aa50250dSMatthew G. Knepley @*/ 5197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5198d71ae5a4SJacob Faibussowitsch { 5199aa50250dSMatthew G. Knepley PetscFunctionBegin; 5200aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52014f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5202c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 52033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5204aa50250dSMatthew G. Knepley } 5205aa50250dSMatthew G. Knepley 5206aa50250dSMatthew G. Knepley /*@ 5207aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5208aa50250dSMatthew G. Knepley 5209aa50250dSMatthew G. Knepley Not Collective 5210aa50250dSMatthew G. Knepley 5211aa50250dSMatthew G. Knepley Input Parameter: 5212a1cb98faSBarry Smith . dm - The `DMPLEX` object 5213aa50250dSMatthew G. Knepley 5214aa50250dSMatthew G. Knepley Output Parameter: 5215aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5216aa50250dSMatthew G. Knepley 5217aa50250dSMatthew G. Knepley Level: developer 5218552f7358SJed Brown 5219b1bb481bSMatthew Knepley Notes: 5220a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5221a1cb98faSBarry Smith 5222a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5223a1cb98faSBarry Smith 5224dc287ab2SVaclav Hapla An empty mesh gives -1. 5225b1bb481bSMatthew Knepley 52261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5227552f7358SJed Brown @*/ 5228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5229d71ae5a4SJacob Faibussowitsch { 52309f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5231aa50250dSMatthew G. Knepley DMLabel label; 5232aa50250dSMatthew G. Knepley PetscInt d = 0; 5233552f7358SJed Brown 5234552f7358SJed Brown PetscFunctionBegin; 5235552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52364f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52379f4ada15SMatthew G. Knepley if (mesh->tr) { 52389f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52399f4ada15SMatthew G. Knepley } else { 52409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52419566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5242552f7358SJed Brown *depth = d - 1; 52439f4ada15SMatthew G. Knepley } 52443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5245552f7358SJed Brown } 5246552f7358SJed Brown 5247552f7358SJed Brown /*@ 524820f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5249552f7358SJed Brown 5250552f7358SJed Brown Not Collective 5251552f7358SJed Brown 5252552f7358SJed Brown Input Parameters: 5253a1cb98faSBarry Smith + dm - The `DMPLEX` object 5254570fa34dSVaclav Hapla - depth - The requested depth 5255552f7358SJed Brown 5256552f7358SJed Brown Output Parameters: 525720f4b53cSBarry Smith + start - The first point at this `depth` 525820f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5259552f7358SJed Brown 5260552f7358SJed Brown Level: developer 5261552f7358SJed Brown 5262a1cb98faSBarry Smith Notes: 5263a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5264a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5265a1cb98faSBarry Smith higher dimension, e.g., "edges". 5266a1cb98faSBarry Smith 52672827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5268552f7358SJed Brown @*/ 5269d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5270d71ae5a4SJacob Faibussowitsch { 52719f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5272aa50250dSMatthew G. Knepley DMLabel label; 527363d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5274552f7358SJed Brown 5275552f7358SJed Brown PetscFunctionBegin; 5276552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52779371c9d4SSatish Balay if (start) { 52784f572ea9SToby Isaac PetscAssertPointer(start, 3); 52799371c9d4SSatish Balay *start = 0; 52809371c9d4SSatish Balay } 52819371c9d4SSatish Balay if (end) { 52824f572ea9SToby Isaac PetscAssertPointer(end, 4); 52839371c9d4SSatish Balay *end = 0; 52849371c9d4SSatish Balay } 52859566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52863ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5287570fa34dSVaclav Hapla if (depth < 0) { 528863d1a920SMatthew G. Knepley if (start) *start = pStart; 528963d1a920SMatthew G. Knepley if (end) *end = pEnd; 52903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5291552f7358SJed Brown } 52929f4ada15SMatthew G. Knepley if (mesh->tr) { 52939f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52949f4ada15SMatthew G. Knepley } else { 52959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 529628b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5297570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52989f4ada15SMatthew G. Knepley } 52993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5300552f7358SJed Brown } 5301552f7358SJed Brown 5302552f7358SJed Brown /*@ 530320f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5304552f7358SJed Brown 5305552f7358SJed Brown Not Collective 5306552f7358SJed Brown 5307552f7358SJed Brown Input Parameters: 5308a1cb98faSBarry Smith + dm - The `DMPLEX` object 5309570fa34dSVaclav Hapla - height - The requested height 5310552f7358SJed Brown 5311552f7358SJed Brown Output Parameters: 531220f4b53cSBarry Smith + start - The first point at this `height` 531320f4b53cSBarry Smith - end - One beyond the last point at this `height` 5314552f7358SJed Brown 5315552f7358SJed Brown Level: developer 5316552f7358SJed Brown 5317a1cb98faSBarry Smith Notes: 5318a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5319a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5320a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5321a1cb98faSBarry Smith 53222827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5323552f7358SJed Brown @*/ 5324d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5325d71ae5a4SJacob Faibussowitsch { 5326aa50250dSMatthew G. Knepley DMLabel label; 532763d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5328552f7358SJed Brown 5329552f7358SJed Brown PetscFunctionBegin; 5330552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53319371c9d4SSatish Balay if (start) { 53324f572ea9SToby Isaac PetscAssertPointer(start, 3); 53339371c9d4SSatish Balay *start = 0; 53349371c9d4SSatish Balay } 53359371c9d4SSatish Balay if (end) { 53364f572ea9SToby Isaac PetscAssertPointer(end, 4); 53379371c9d4SSatish Balay *end = 0; 53389371c9d4SSatish Balay } 53399566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53403ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5341570fa34dSVaclav Hapla if (height < 0) { 534263d1a920SMatthew G. Knepley if (start) *start = pStart; 534363d1a920SMatthew G. Knepley if (end) *end = pEnd; 53443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5345552f7358SJed Brown } 53469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 534759e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 534859e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 534959e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 535059e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5352552f7358SJed Brown } 5353552f7358SJed Brown 5354ba2698f1SMatthew G. Knepley /*@ 535520f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5356ba2698f1SMatthew G. Knepley 5357ba2698f1SMatthew G. Knepley Not Collective 5358ba2698f1SMatthew G. Knepley 5359d8d19677SJose E. Roman Input Parameters: 5360a1cb98faSBarry Smith + dm - The `DMPLEX` object 5361ba2698f1SMatthew G. Knepley - point - The point 5362ba2698f1SMatthew G. Knepley 5363ba2698f1SMatthew G. Knepley Output Parameter: 536420f4b53cSBarry Smith . depth - The depth of the `point` 5365ba2698f1SMatthew G. Knepley 5366ba2698f1SMatthew G. Knepley Level: intermediate 5367ba2698f1SMatthew G. Knepley 53681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5369ba2698f1SMatthew G. Knepley @*/ 5370d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5371d71ae5a4SJacob Faibussowitsch { 5372ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5373ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53744f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53759566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5377ba2698f1SMatthew G. Knepley } 5378ba2698f1SMatthew G. Knepley 5379ba2698f1SMatthew G. Knepley /*@ 538020f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53810c0a32dcSVaclav Hapla 53820c0a32dcSVaclav Hapla Not Collective 53830c0a32dcSVaclav Hapla 5384d8d19677SJose E. Roman Input Parameters: 5385a1cb98faSBarry Smith + dm - The `DMPLEX` object 53860c0a32dcSVaclav Hapla - point - The point 53870c0a32dcSVaclav Hapla 53880c0a32dcSVaclav Hapla Output Parameter: 538920f4b53cSBarry Smith . height - The height of the `point` 53900c0a32dcSVaclav Hapla 53910c0a32dcSVaclav Hapla Level: intermediate 53920c0a32dcSVaclav Hapla 53931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53940c0a32dcSVaclav Hapla @*/ 5395d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5396d71ae5a4SJacob Faibussowitsch { 53970c0a32dcSVaclav Hapla PetscInt n, pDepth; 53980c0a32dcSVaclav Hapla 53990c0a32dcSVaclav Hapla PetscFunctionBegin; 54000c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54014f572ea9SToby Isaac PetscAssertPointer(height, 3); 54029566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 54039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 54040c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 54053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54060c0a32dcSVaclav Hapla } 54070c0a32dcSVaclav Hapla 54080c0a32dcSVaclav Hapla /*@ 5409a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5410ba2698f1SMatthew G. Knepley 5411ba2698f1SMatthew G. Knepley Not Collective 5412ba2698f1SMatthew G. Knepley 5413ba2698f1SMatthew G. Knepley Input Parameter: 5414a1cb98faSBarry Smith . dm - The `DMPLEX` object 5415ba2698f1SMatthew G. Knepley 5416ba2698f1SMatthew G. Knepley Output Parameter: 5417a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5418412e9a14SMatthew G. Knepley 5419ba2698f1SMatthew G. Knepley Level: developer 5420ba2698f1SMatthew G. Knepley 5421a1cb98faSBarry Smith Note: 5422a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5423a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5424a1cb98faSBarry Smith 54251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5426ba2698f1SMatthew G. Knepley @*/ 5427d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5428d71ae5a4SJacob Faibussowitsch { 5429ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5430ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54314f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 54329566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5433ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5435ba2698f1SMatthew G. Knepley } 5436ba2698f1SMatthew G. Knepley 5437ba2698f1SMatthew G. Knepley /*@ 5438ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5439ba2698f1SMatthew G. Knepley 5440ba2698f1SMatthew G. Knepley Not Collective 5441ba2698f1SMatthew G. Knepley 5442d8d19677SJose E. Roman Input Parameters: 5443a1cb98faSBarry Smith + dm - The `DMPLEX` object 5444ba2698f1SMatthew G. Knepley - cell - The cell 5445ba2698f1SMatthew G. Knepley 5446ba2698f1SMatthew G. Knepley Output Parameter: 5447ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5448ba2698f1SMatthew G. Knepley 5449ba2698f1SMatthew G. Knepley Level: intermediate 5450ba2698f1SMatthew G. Knepley 54511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5452ba2698f1SMatthew G. Knepley @*/ 5453d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5454d71ae5a4SJacob Faibussowitsch { 54559f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5456ba2698f1SMatthew G. Knepley DMLabel label; 5457ba2698f1SMatthew G. Knepley PetscInt ct; 5458ba2698f1SMatthew G. Knepley 5459ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5460ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54614f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54629f4ada15SMatthew G. Knepley if (mesh->tr) { 54639f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54649f4ada15SMatthew G. Knepley } else { 546521027e53SStefano Zampini PetscInt pStart, pEnd; 546621027e53SStefano Zampini 546721027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 546821027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 546921027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 547021027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 547121027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 547221027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 547321027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 547421027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 547521027e53SStefano Zampini } 547621027e53SStefano Zampini } 547721027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 547821027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54809566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 548163a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5482936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 548321027e53SStefano Zampini } 54849f4ada15SMatthew G. Knepley } 54853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5486ba2698f1SMatthew G. Knepley } 5487ba2698f1SMatthew G. Knepley 5488412e9a14SMatthew G. Knepley /*@ 5489412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5490412e9a14SMatthew G. Knepley 5491412e9a14SMatthew G. Knepley Not Collective 5492412e9a14SMatthew G. Knepley 5493412e9a14SMatthew G. Knepley Input Parameters: 5494a1cb98faSBarry Smith + dm - The `DMPLEX` object 5495412e9a14SMatthew G. Knepley . cell - The cell 5496412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5497412e9a14SMatthew G. Knepley 5498a1cb98faSBarry Smith Level: advanced 5499a1cb98faSBarry Smith 5500a1cb98faSBarry Smith Note: 5501a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5502412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5503412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5504db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5505412e9a14SMatthew G. Knepley 55061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5507412e9a14SMatthew G. Knepley @*/ 5508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5509d71ae5a4SJacob Faibussowitsch { 551021027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5511412e9a14SMatthew G. Knepley DMLabel label; 551221027e53SStefano Zampini PetscInt pStart, pEnd; 5513412e9a14SMatthew G. Knepley 5514412e9a14SMatthew G. Knepley PetscFunctionBegin; 5515412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 551621027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 55179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 55189566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 551921027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 552021027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 55213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5522412e9a14SMatthew G. Knepley } 5523412e9a14SMatthew G. Knepley 5524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5525d71ae5a4SJacob Faibussowitsch { 5526efe440bfSMatthew G. Knepley PetscSection section, s; 5527efe440bfSMatthew G. Knepley Mat m; 55283e922f36SToby Isaac PetscInt maxHeight; 5529dd4c3f67SMatthew G. Knepley const char *prefix; 5530552f7358SJed Brown 5531552f7358SJed Brown PetscFunctionBegin; 55329566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5533dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5534dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5535dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55369566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55379566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55399566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 55429566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 55439566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 55449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 55459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 55468f4c458bSMatthew G. Knepley 55479566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55489566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5549dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5550dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5552552f7358SJed Brown } 5553552f7358SJed Brown 5554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5555d71ae5a4SJacob Faibussowitsch { 55566858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55576858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5558f19dbd58SToby Isaac 5559f19dbd58SToby Isaac PetscFunctionBegin; 5560f19dbd58SToby Isaac *field = NULL; 55619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55636858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55646858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5565f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55666858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55676858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5568f19dbd58SToby Isaac } 55693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5570f19dbd58SToby Isaac } 5571f19dbd58SToby Isaac 55727cd05799SMatthew G. Knepley /*@C 55737cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55747cd05799SMatthew G. Knepley 55757cd05799SMatthew G. Knepley Not Collective 55767cd05799SMatthew G. Knepley 55772fe279fdSBarry Smith Input Parameter: 5578a1cb98faSBarry Smith . dm - The `DMPLEX` object 55797cd05799SMatthew G. Knepley 55807cd05799SMatthew G. Knepley Output Parameter: 5581a1cb98faSBarry Smith . section - The `PetscSection` object 55827cd05799SMatthew G. Knepley 55837cd05799SMatthew G. Knepley Level: developer 55847cd05799SMatthew G. Knepley 55851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55867cd05799SMatthew G. Knepley @*/ 5587d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5588d71ae5a4SJacob Faibussowitsch { 5589552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5590552f7358SJed Brown 5591552f7358SJed Brown PetscFunctionBegin; 5592552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5593552f7358SJed Brown if (section) *section = mesh->coneSection; 55943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5595552f7358SJed Brown } 5596552f7358SJed Brown 55977cd05799SMatthew G. Knepley /*@C 55987cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55997cd05799SMatthew G. Knepley 56007cd05799SMatthew G. Knepley Not Collective 56017cd05799SMatthew G. Knepley 56022fe279fdSBarry Smith Input Parameter: 5603a1cb98faSBarry Smith . dm - The `DMPLEX` object 56047cd05799SMatthew G. Knepley 56057cd05799SMatthew G. Knepley Output Parameter: 5606a1cb98faSBarry Smith . section - The `PetscSection` object 56077cd05799SMatthew G. Knepley 56087cd05799SMatthew G. Knepley Level: developer 56097cd05799SMatthew G. Knepley 56101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 56117cd05799SMatthew G. Knepley @*/ 5612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5613d71ae5a4SJacob Faibussowitsch { 56148cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 56158cb4d582SMatthew G. Knepley 56168cb4d582SMatthew G. Knepley PetscFunctionBegin; 56178cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56188cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 56193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56208cb4d582SMatthew G. Knepley } 56218cb4d582SMatthew G. Knepley 56227cd05799SMatthew G. Knepley /*@C 56237cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 56247cd05799SMatthew G. Knepley 56257cd05799SMatthew G. Knepley Not Collective 56267cd05799SMatthew G. Knepley 56272fe279fdSBarry Smith Input Parameter: 5628a1cb98faSBarry Smith . dm - The `DMPLEX` object 56297cd05799SMatthew G. Knepley 56307cd05799SMatthew G. Knepley Output Parameter: 56317cd05799SMatthew G. Knepley . cones - The cone for each point 56327cd05799SMatthew G. Knepley 56337cd05799SMatthew G. Knepley Level: developer 56347cd05799SMatthew G. Knepley 56351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56367cd05799SMatthew G. Knepley @*/ 5637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5638d71ae5a4SJacob Faibussowitsch { 5639552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5640552f7358SJed Brown 5641552f7358SJed Brown PetscFunctionBegin; 5642552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5643552f7358SJed Brown if (cones) *cones = mesh->cones; 56443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5645552f7358SJed Brown } 5646552f7358SJed Brown 56477cd05799SMatthew G. Knepley /*@C 56487cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56497cd05799SMatthew G. Knepley 56507cd05799SMatthew G. Knepley Not Collective 56517cd05799SMatthew G. Knepley 56522fe279fdSBarry Smith Input Parameter: 5653a1cb98faSBarry Smith . dm - The `DMPLEX` object 56547cd05799SMatthew G. Knepley 56557cd05799SMatthew G. Knepley Output Parameter: 5656b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56577cd05799SMatthew G. Knepley 56587cd05799SMatthew G. Knepley Level: developer 56597cd05799SMatthew G. Knepley 5660b5a892a1SMatthew G. Knepley Notes: 5661a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5662b5a892a1SMatthew G. Knepley 5663a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5664b5a892a1SMatthew G. Knepley 56651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56667cd05799SMatthew G. Knepley @*/ 5667d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5668d71ae5a4SJacob Faibussowitsch { 5669552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5670552f7358SJed Brown 5671552f7358SJed Brown PetscFunctionBegin; 5672552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5673552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5675552f7358SJed Brown } 5676552f7358SJed Brown 5677552f7358SJed Brown /******************************** FEM Support **********************************/ 5678552f7358SJed Brown 5679d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5680d2b2dc1eSMatthew G. Knepley { 5681d2b2dc1eSMatthew G. Knepley PetscInt depth; 5682d2b2dc1eSMatthew G. Knepley 5683d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5684d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5685d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5686d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5687d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5688d2b2dc1eSMatthew G. Knepley } 5689d2b2dc1eSMatthew G. Knepley 56905962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56915962854dSMatthew G. Knepley { 56925962854dSMatthew G. Knepley PetscInt depth; 56935962854dSMatthew G. Knepley 56945962854dSMatthew G. Knepley PetscFunctionBegin; 56955962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56965962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56975962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56985962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56995962854dSMatthew G. Knepley } 57005962854dSMatthew G. Knepley 57019e8305c2SJed Brown /* 57029e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 57039e8305c2SJed Brown representing a line in the section. 57049e8305c2SJed Brown */ 57055f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5706d71ae5a4SJacob Faibussowitsch { 5707e327e467SRezgar Shakeri PetscObject obj; 5708e327e467SRezgar Shakeri PetscClassId id; 5709e327e467SRezgar Shakeri PetscFE fe = NULL; 5710e327e467SRezgar Shakeri 57119e8305c2SJed Brown PetscFunctionBeginHot; 57129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5713e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5714e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5715e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5716e327e467SRezgar Shakeri 5717e327e467SRezgar Shakeri if (!fe) { 5718e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 57199e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 57209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 57219e8305c2SJed Brown *k = *k / *Nc + 1; 5722e327e467SRezgar Shakeri } else { 5723e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 57245f82726aSMatthew G. Knepley PetscDualSpace dsp; 57255f82726aSMatthew G. Knepley 5726e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 57275f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 57285f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5729e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 57305f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 57315f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 57325f82726aSMatthew G. Knepley } 57335f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 57345f82726aSMatthew G. Knepley } 57355f82726aSMatthew G. Knepley 57365f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 57375f82726aSMatthew G. Knepley { 57385f82726aSMatthew G. Knepley PetscFunctionBeginHot; 57395f82726aSMatthew G. Knepley if (tensor) { 57405f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 57415f82726aSMatthew G. Knepley } else { 57425f82726aSMatthew G. Knepley switch (dim) { 57435f82726aSMatthew G. Knepley case 1: 57445f82726aSMatthew G. Knepley *dof = k + 1; 57455f82726aSMatthew G. Knepley break; 57465f82726aSMatthew G. Knepley case 2: 57475f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 57485f82726aSMatthew G. Knepley break; 57495f82726aSMatthew G. Knepley case 3: 57505f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 57515f82726aSMatthew G. Knepley break; 57525f82726aSMatthew G. Knepley default: 57535f82726aSMatthew G. Knepley *dof = 0; 57545f82726aSMatthew G. Knepley } 57559e8305c2SJed Brown } 57563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57579e8305c2SJed Brown } 57589e8305c2SJed Brown 5759a4355906SMatthew Knepley /*@ 5760bc1eb3faSJed Brown 5761bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5762bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 576320f4b53cSBarry Smith section provided (or the section of the `DM`). 5764a4355906SMatthew Knepley 5765a4355906SMatthew Knepley Input Parameters: 576620f4b53cSBarry Smith + dm - The `DM` 576720f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 576820f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5769a4355906SMatthew Knepley 5770bc1eb3faSJed Brown Example: 5771bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5772bc1eb3faSJed Brown .vb 5773bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5774bc1eb3faSJed Brown 5775bc1eb3faSJed Brown v4 -- e6 -- v3 5776bc1eb3faSJed Brown | | 5777bc1eb3faSJed Brown e7 c0 e8 5778bc1eb3faSJed Brown | | 5779bc1eb3faSJed Brown v1 -- e5 -- v2 5780bc1eb3faSJed Brown .ve 5781bc1eb3faSJed Brown 5782bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5783bc1eb3faSJed Brown dofs in the order of points, e.g., 5784bc1eb3faSJed Brown .vb 5785bc1eb3faSJed Brown c0 -> [0,1,2,3] 5786bc1eb3faSJed Brown v1 -> [4] 5787bc1eb3faSJed Brown ... 5788bc1eb3faSJed Brown e5 -> [8, 9] 5789bc1eb3faSJed Brown .ve 5790bc1eb3faSJed Brown 5791bc1eb3faSJed Brown which corresponds to the dofs 5792bc1eb3faSJed Brown .vb 5793bc1eb3faSJed Brown 6 10 11 7 5794bc1eb3faSJed Brown 13 2 3 15 5795bc1eb3faSJed Brown 12 0 1 14 5796bc1eb3faSJed Brown 4 8 9 5 5797bc1eb3faSJed Brown .ve 5798bc1eb3faSJed Brown 5799bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5800bc1eb3faSJed Brown .vb 5801bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5802bc1eb3faSJed Brown .ve 5803bc1eb3faSJed Brown 5804bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5805bc1eb3faSJed Brown .vb 5806bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5807bc1eb3faSJed Brown .ve 5808bc1eb3faSJed Brown 5809a4355906SMatthew Knepley Level: developer 5810a4355906SMatthew Knepley 5811da9ac489SAlbert Cowie Notes: 5812a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5813a1cb98faSBarry Smith degree of the basis. 5814a1cb98faSBarry Smith 5815da9ac489SAlbert Cowie This is required to run with libCEED. 5816da9ac489SAlbert Cowie 58171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5818a4355906SMatthew Knepley @*/ 5819d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5820d71ae5a4SJacob Faibussowitsch { 58217391a63aSMatthew G. Knepley DMLabel label; 5822bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 58235f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 58243194fc30SMatthew G. Knepley 58253194fc30SMatthew G. Knepley PetscFunctionBegin; 58269566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 58273ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5828a433471fSStefano Zampini if (point < 0) { 5829a433471fSStefano Zampini PetscInt sStart, sEnd; 5830a433471fSStefano Zampini 58319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5832a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5833a433471fSStefano Zampini } 58349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 58359566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 58369566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 58379371c9d4SSatish Balay if (depth == 1) { 58389371c9d4SSatish Balay eStart = point; 58399371c9d4SSatish Balay } else if (depth == dim) { 58407391a63aSMatthew G. Knepley const PetscInt *cone; 58417391a63aSMatthew G. Knepley 58429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5843d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5844d4e6627bSStefano Zampini else if (dim == 3) { 5845d4e6627bSStefano Zampini const PetscInt *cone2; 58469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5847d4e6627bSStefano Zampini eStart = cone2[0]; 584863a3b9bcSJacob 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); 584963a3b9bcSJacob 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); 5850e327e467SRezgar Shakeri 58519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5852bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5853bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5854bb197d40SJed Brown PetscInt *perm; 5855bb197d40SJed Brown 58563194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 58575f82726aSMatthew G. Knepley PetscInt dof; 58585f82726aSMatthew G. Knepley 58595f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58605f82726aSMatthew 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); 58615f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58625f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58635f82726aSMatthew G. Knepley size += dof * Nc; 58643194fc30SMatthew G. Knepley } 58659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58663194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5867bb197d40SJed Brown switch (d) { 5868babf31e0SJed Brown case 1: 58695f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58705f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5871babf31e0SJed Brown /* 5872babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5873babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5874babf31e0SJed Brown */ 5875e327e467SRezgar Shakeri if (continuous) { 5876babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58779371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58789371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5879babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5880babf31e0SJed Brown foffset = offset; 5881e327e467SRezgar Shakeri } else { 58825f82726aSMatthew G. Knepley PetscInt dof; 58835f82726aSMatthew G. Knepley 58845f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 58855f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 58865f82726aSMatthew G. Knepley foffset = offset; 5887e327e467SRezgar Shakeri } 5888babf31e0SJed Brown break; 588989eabcffSMatthew G. Knepley case 2: 58903194fc30SMatthew 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} */ 58915f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 58925f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 58933194fc30SMatthew G. Knepley /* The SEM order is 58943194fc30SMatthew G. Knepley 58953194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 589689eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58973194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58983194fc30SMatthew G. Knepley */ 5899e327e467SRezgar Shakeri if (continuous) { 59003194fc30SMatthew G. Knepley const PetscInt of = 0; 59013194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 59023194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 59033194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 59043194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 59053194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 59063194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 59073194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 59083194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 59093194fc30SMatthew G. Knepley PetscInt o; 59103194fc30SMatthew G. Knepley 59113194fc30SMatthew G. Knepley /* bottom */ 59123194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 59139371c9d4SSatish Balay for (o = oeb; o < oer; ++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] = ovrb * Nc + c + foffset; 59163194fc30SMatthew G. Knepley /* middle */ 59173194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 59183194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 59199371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++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] = (oer + i) * Nc + c + foffset; 59223194fc30SMatthew G. Knepley } 59233194fc30SMatthew G. Knepley /* top */ 59243194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 59259371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 59269371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59273194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 59283194fc30SMatthew G. Knepley foffset = offset; 5929e327e467SRezgar Shakeri } else { 59305f82726aSMatthew G. Knepley PetscInt dof; 59315f82726aSMatthew G. Knepley 59325f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59335f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 59345f82726aSMatthew G. Knepley foffset = offset; 59353194fc30SMatthew G. Knepley } 593689eabcffSMatthew G. Knepley break; 593789eabcffSMatthew G. Knepley case 3: 593889eabcffSMatthew G. Knepley /* The original hex closure is 593989eabcffSMatthew G. Knepley 594089eabcffSMatthew G. Knepley {c, 594189eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 594289eabcffSMatthew 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, 594389eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 594489eabcffSMatthew G. Knepley */ 59455f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59465f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 594789eabcffSMatthew G. Knepley /* The SEM order is 594889eabcffSMatthew G. Knepley Bottom Slice 594989eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 595089eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 595189eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 595289eabcffSMatthew G. Knepley 595389eabcffSMatthew G. Knepley Middle Slice (j) 595489eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 595589eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 595689eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 595789eabcffSMatthew G. Knepley 595889eabcffSMatthew G. Knepley Top Slice 595989eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 596089eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 596189eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 596289eabcffSMatthew G. Knepley */ 5963e327e467SRezgar Shakeri if (continuous) { 596489eabcffSMatthew G. Knepley const PetscInt oc = 0; 596589eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 596689eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 596789eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 596889eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 596989eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 597089eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 597189eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 597289eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 597389eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 597489eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 597589eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 597689eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 597789eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 597889eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 597989eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 598089eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 598189eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 598289eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 598389eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 598489eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 598589eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 598689eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 598789eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 598889eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 598989eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 599089eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 599189eabcffSMatthew G. Knepley PetscInt o, n; 599289eabcffSMatthew G. Knepley 599389eabcffSMatthew G. Knepley /* Bottom Slice */ 599489eabcffSMatthew G. Knepley /* bottom */ 599589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59969371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59979371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 599889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 599989eabcffSMatthew G. Knepley /* middle */ 600089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 600189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 60029371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 60039371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 60049371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60059371c9d4SSatish Balay } 600689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 60073194fc30SMatthew G. Knepley } 600889eabcffSMatthew G. Knepley /* top */ 600989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 60109371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 60119371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 601289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 601389eabcffSMatthew G. Knepley 601489eabcffSMatthew G. Knepley /* Middle Slice */ 601589eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 601689eabcffSMatthew G. Knepley /* bottom */ 601789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 60189371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 60199371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 602089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 602189eabcffSMatthew G. Knepley /* middle */ 602289eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 602389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 60249371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60259371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 602689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 602789eabcffSMatthew G. Knepley } 602889eabcffSMatthew G. Knepley /* top */ 602989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 60309371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 60319371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 603289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 603389eabcffSMatthew G. Knepley } 603489eabcffSMatthew G. Knepley 603589eabcffSMatthew G. Knepley /* Top Slice */ 603689eabcffSMatthew G. Knepley /* bottom */ 603789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 60389371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 60399371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 604089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 604189eabcffSMatthew G. Knepley /* middle */ 604289eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 604389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 60449371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 60459371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 604689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 604789eabcffSMatthew G. Knepley } 604889eabcffSMatthew G. Knepley /* top */ 604989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 60509371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 60519371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 605289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 605389eabcffSMatthew G. Knepley 605489eabcffSMatthew G. Knepley foffset = offset; 6055e327e467SRezgar Shakeri } else { 60565f82726aSMatthew G. Knepley PetscInt dof; 60575f82726aSMatthew G. Knepley 60585f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60595f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60605f82726aSMatthew G. Knepley foffset = offset; 606189eabcffSMatthew G. Knepley } 606289eabcffSMatthew G. Knepley break; 6063d71ae5a4SJacob Faibussowitsch default: 6064d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 606589eabcffSMatthew G. Knepley } 606689eabcffSMatthew G. Knepley } 606763a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 60683194fc30SMatthew G. Knepley /* Check permutation */ 60693194fc30SMatthew G. Knepley { 60703194fc30SMatthew G. Knepley PetscInt *check; 60713194fc30SMatthew G. Knepley 60729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 60731dca8a05SBarry Smith for (i = 0; i < size; ++i) { 60741dca8a05SBarry Smith check[i] = -1; 60751dca8a05SBarry 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]); 60761dca8a05SBarry Smith } 60773194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60781dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60799566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60803194fc30SMatthew G. Knepley } 60819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6082a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6083a05c9aa3SJed Brown PetscInt *loc_perm; 60849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6085a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6086a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6087a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6088a05c9aa3SJed Brown } 60899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6090a05c9aa3SJed Brown } 6091bb197d40SJed Brown } 60923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60933194fc30SMatthew G. Knepley } 60943194fc30SMatthew G. Knepley 6095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6096d71ae5a4SJacob Faibussowitsch { 6097e071409bSToby Isaac PetscDS prob; 6098e071409bSToby Isaac PetscInt depth, Nf, h; 6099e071409bSToby Isaac DMLabel label; 6100e071409bSToby Isaac 6101e071409bSToby Isaac PetscFunctionBeginHot; 61029566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6103e071409bSToby Isaac Nf = prob->Nf; 6104e071409bSToby Isaac label = dm->depthLabel; 6105e071409bSToby Isaac *dspace = NULL; 6106e071409bSToby Isaac if (field < Nf) { 6107e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6108e071409bSToby Isaac 6109e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6110e071409bSToby Isaac PetscDualSpace dsp; 6111e071409bSToby Isaac 61129566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 61139566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 61149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6115e071409bSToby Isaac h = depth - 1 - h; 6116e071409bSToby Isaac if (h) { 61179566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6118e071409bSToby Isaac } else { 6119e071409bSToby Isaac *dspace = dsp; 6120e071409bSToby Isaac } 6121e071409bSToby Isaac } 6122e071409bSToby Isaac } 61233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6124e071409bSToby Isaac } 6125e071409bSToby Isaac 6126d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6127d71ae5a4SJacob Faibussowitsch { 612828351e22SJed Brown PetscScalar *array; 612928351e22SJed Brown const PetscScalar *vArray; 6130d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 61311a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6132552f7358SJed Brown 61331b406b76SMatthew G. Knepley PetscFunctionBeginHot; 61349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 61359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 61369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 61379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 61383f7cbbe7SMatthew G. Knepley if (!values || !*values) { 61399df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61409df71ca4SMatthew G. Knepley PetscInt dof; 6141d9917b9dSMatthew G. Knepley 61429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61439df71ca4SMatthew G. Knepley size += dof; 61449df71ca4SMatthew G. Knepley } 61459df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61469df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61472a3aaacfSMatthew G. Knepley PetscInt dof; 61485a1bb5cfSMatthew G. Knepley 61495a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61515a1bb5cfSMatthew G. Knepley size += dof; 61525a1bb5cfSMatthew G. Knepley } 61533f7cbbe7SMatthew G. Knepley if (!values) { 61543f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 61553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61563f7cbbe7SMatthew G. Knepley } 61579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6158982e9ed1SMatthew G. Knepley } else { 6159982e9ed1SMatthew G. Knepley array = *values; 6160982e9ed1SMatthew G. Knepley } 61619df71ca4SMatthew G. Knepley size = 0; 616228351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 61639df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 61649df71ca4SMatthew G. Knepley PetscInt dof, off, d; 616528351e22SJed Brown const PetscScalar *varr; 6166d9917b9dSMatthew G. Knepley 61679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 61689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 61698e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6170ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61719df71ca4SMatthew G. Knepley size += dof; 61729df71ca4SMatthew G. Knepley } 61739df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 61749df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61759df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61765a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 617728351e22SJed Brown const PetscScalar *varr; 61785a1bb5cfSMatthew G. Knepley 617952ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61828e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 61835a1bb5cfSMatthew G. Knepley if (o >= 0) { 6184ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61855a1bb5cfSMatthew G. Knepley } else { 6186ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61875a1bb5cfSMatthew G. Knepley } 61889df71ca4SMatthew G. Knepley size += dof; 61895a1bb5cfSMatthew G. Knepley } 619028351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61919df71ca4SMatthew G. Knepley if (!*values) { 61925a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61935a1bb5cfSMatthew G. Knepley *values = array; 61949df71ca4SMatthew G. Knepley } else { 619563a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61968c312ff3SMatthew G. Knepley *csize = size; 61979df71ca4SMatthew G. Knepley } 61983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61995a1bb5cfSMatthew G. Knepley } 6200d9917b9dSMatthew G. Knepley 620127f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6202d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6203d71ae5a4SJacob Faibussowitsch { 620427f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 620527f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 620627f02ce8SMatthew G. Knepley 62079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 620827f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 620927f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 621027f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 621127f02ce8SMatthew G. Knepley points[q * 2] = r; 621227f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 621327f02ce8SMatthew G. Knepley ++q; 621427f02ce8SMatthew G. Knepley } 621527f02ce8SMatthew G. Knepley } 621627f02ce8SMatthew G. Knepley *numPoints = q; 62173ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 621827f02ce8SMatthew G. Knepley } 621927f02ce8SMatthew G. Knepley 622097529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 622107218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6222d71ae5a4SJacob Faibussowitsch { 622327f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6224923c78e0SToby Isaac PetscInt np, *pts = NULL; 6225923c78e0SToby Isaac 6226923c78e0SToby Isaac PetscFunctionBeginHot; 62279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 622807218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6229923c78e0SToby Isaac PetscInt dof, off; 6230923c78e0SToby Isaac 62319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 62329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 62339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6234923c78e0SToby Isaac np = dof / 2; 62358e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 623627f02ce8SMatthew G. Knepley } else { 623707218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 62389566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6239923c78e0SToby Isaac } 6240923c78e0SToby Isaac *numPoints = np; 6241923c78e0SToby Isaac *points = pts; 6242923c78e0SToby Isaac *clp = cla; 62433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6244923c78e0SToby Isaac } 6245923c78e0SToby Isaac 6246d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6247d71ae5a4SJacob Faibussowitsch { 6248923c78e0SToby Isaac PetscFunctionBeginHot; 6249923c78e0SToby Isaac if (!*clPoints) { 62509566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6251923c78e0SToby Isaac } else { 62529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6253923c78e0SToby Isaac } 6254923c78e0SToby Isaac *numPoints = 0; 6255923c78e0SToby Isaac *points = NULL; 6256923c78e0SToby Isaac *clSec = NULL; 6257923c78e0SToby Isaac *clPoints = NULL; 6258923c78e0SToby Isaac *clp = NULL; 62593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6260923c78e0SToby Isaac } 6261923c78e0SToby Isaac 6262d71ae5a4SJacob 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[]) 6263d71ae5a4SJacob Faibussowitsch { 62641a271a75SMatthew G. Knepley PetscInt offset = 0, p; 626597e99dd9SToby Isaac const PetscInt **perms = NULL; 626697e99dd9SToby Isaac const PetscScalar **flips = NULL; 62671a271a75SMatthew G. Knepley 62681a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6269fe02ba77SJed Brown *size = 0; 62709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 627197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 627297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 627397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 627497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62751a271a75SMatthew G. Knepley PetscInt dof, off, d; 62761a271a75SMatthew G. Knepley const PetscScalar *varr; 62771a271a75SMatthew G. Knepley 62789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62808e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 628197e99dd9SToby Isaac if (clperm) { 628297e99dd9SToby Isaac if (perm) { 628397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62841a271a75SMatthew G. Knepley } else { 628597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 628697e99dd9SToby Isaac } 628797e99dd9SToby Isaac if (flip) { 628897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 628997e99dd9SToby Isaac } 629097e99dd9SToby Isaac } else { 629197e99dd9SToby Isaac if (perm) { 629297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 629397e99dd9SToby Isaac } else { 629497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 629597e99dd9SToby Isaac } 629697e99dd9SToby Isaac if (flip) { 629797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62981a271a75SMatthew G. Knepley } 62991a271a75SMatthew G. Knepley } 630097e99dd9SToby Isaac offset += dof; 630197e99dd9SToby Isaac } 63029566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 63031a271a75SMatthew G. Knepley *size = offset; 63043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63051a271a75SMatthew G. Knepley } 63061a271a75SMatthew G. Knepley 6307d71ae5a4SJacob 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[]) 6308d71ae5a4SJacob Faibussowitsch { 63091a271a75SMatthew G. Knepley PetscInt offset = 0, f; 63101a271a75SMatthew G. Knepley 63111a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6312fe02ba77SJed Brown *size = 0; 63131a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 631497e99dd9SToby Isaac PetscInt p; 631597e99dd9SToby Isaac const PetscInt **perms = NULL; 631697e99dd9SToby Isaac const PetscScalar **flips = NULL; 63171a271a75SMatthew G. Knepley 63189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 631997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 632097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 632197e99dd9SToby Isaac PetscInt fdof, foff, b; 63221a271a75SMatthew G. Knepley const PetscScalar *varr; 632397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 632497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63251a271a75SMatthew G. Knepley 63269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 63279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 63281a271a75SMatthew G. Knepley varr = &vArray[foff]; 632997e99dd9SToby Isaac if (clperm) { 63309371c9d4SSatish Balay if (perm) { 6331ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 63321a271a75SMatthew G. Knepley } else { 6333ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 63349371c9d4SSatish Balay } 63359371c9d4SSatish Balay if (flip) { 6336ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 63379371c9d4SSatish Balay } 63389371c9d4SSatish Balay } else { 63399371c9d4SSatish Balay if (perm) { 6340ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 63419371c9d4SSatish Balay } else { 6342ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 63439371c9d4SSatish Balay } 63449371c9d4SSatish Balay if (flip) { 6345ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 63469371c9d4SSatish Balay } 63471a271a75SMatthew G. Knepley } 634897e99dd9SToby Isaac offset += fdof; 63491a271a75SMatthew G. Knepley } 63509566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 63511a271a75SMatthew G. Knepley } 63521a271a75SMatthew G. Knepley *size = offset; 63533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63541a271a75SMatthew G. Knepley } 63551a271a75SMatthew G. Knepley 6356e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 635707218a29SMatthew G. Knepley { 635807218a29SMatthew G. Knepley PetscSection clSection; 635907218a29SMatthew G. Knepley IS clPoints; 636007218a29SMatthew G. Knepley PetscInt *points = NULL; 6361e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 636207218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 636307218a29SMatthew G. Knepley 636407218a29SMatthew G. Knepley PetscFunctionBeginHot; 636507218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 636607218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 636707218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6368e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 636907218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 637007218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 637107218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 637207218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 637307218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 637407218a29SMatthew G. Knepley } 637507218a29SMatthew G. Knepley /* Get points */ 637607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 637707218a29SMatthew G. Knepley /* Get sizes */ 637807218a29SMatthew G. Knepley asize = 0; 637907218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 638007218a29SMatthew G. Knepley PetscInt dof; 638107218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 638207218a29SMatthew G. Knepley asize += dof; 638307218a29SMatthew G. Knepley } 638407218a29SMatthew G. Knepley if (values) { 638507218a29SMatthew G. Knepley const PetscScalar *vArray; 638607218a29SMatthew G. Knepley PetscInt size; 638707218a29SMatthew G. Knepley 638807218a29SMatthew G. Knepley if (*values) { 638907218a29SMatthew 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); 639007218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6391e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 639207218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 639307218a29SMatthew G. Knepley /* Get values */ 639407218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 639507218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 639607218a29SMatthew 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); 639707218a29SMatthew G. Knepley /* Cleanup array */ 639807218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 639907218a29SMatthew G. Knepley } 640007218a29SMatthew G. Knepley if (csize) *csize = asize; 640107218a29SMatthew G. Knepley /* Cleanup points */ 640207218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 640307218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 640407218a29SMatthew G. Knepley } 640507218a29SMatthew G. Knepley 6406552f7358SJed Brown /*@C 6407552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6408552f7358SJed Brown 6409552f7358SJed Brown Not collective 6410552f7358SJed Brown 6411552f7358SJed Brown Input Parameters: 6412a1cb98faSBarry Smith + dm - The `DM` 641320f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6414552f7358SJed Brown . v - The local vector 6415a1cb98faSBarry Smith - point - The point in the `DM` 6416552f7358SJed Brown 64176b867d5aSJose E. Roman Input/Output Parameters: 641820f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 641920f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 642020f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 642122c1ee49SMatthew G. Knepley 6422552f7358SJed Brown Level: intermediate 6423552f7358SJed Brown 6424a1cb98faSBarry Smith Notes: 642520f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6426a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6427a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6428a1cb98faSBarry Smith 6429a1cb98faSBarry Smith A typical use could be 6430a1cb98faSBarry Smith .vb 6431a1cb98faSBarry Smith values = NULL; 6432a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6433a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6434a1cb98faSBarry Smith <Compute on closure> 6435a1cb98faSBarry Smith } 6436a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6437a1cb98faSBarry Smith .ve 6438a1cb98faSBarry Smith or 6439a1cb98faSBarry Smith .vb 6440a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6441a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6442a1cb98faSBarry Smith clSize = clMaxSize; 6443a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6444a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6445a1cb98faSBarry Smith <Compute on closure> 6446a1cb98faSBarry Smith } 6447a1cb98faSBarry Smith } 6448a1cb98faSBarry Smith PetscFree(values); 6449a1cb98faSBarry Smith .ve 6450a1cb98faSBarry Smith 645160225df5SJacob Faibussowitsch Fortran Notes: 645220f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6453a1cb98faSBarry Smith 64541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6455552f7358SJed Brown @*/ 6456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6457d71ae5a4SJacob Faibussowitsch { 6458d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6459e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 64603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6461552f7358SJed Brown } 6462552f7358SJed Brown 6463d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6464d71ae5a4SJacob Faibussowitsch { 6465e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6466e5c487bfSMatthew G. Knepley PetscSection clSection; 6467e5c487bfSMatthew G. Knepley IS clPoints; 6468e5c487bfSMatthew G. Knepley PetscScalar *array; 6469e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6470e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6471c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6472c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6473e5c487bfSMatthew G. Knepley 6474e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6475e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64769566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6477e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6478e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6482e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64839566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6485e5c487bfSMatthew G. Knepley } 6486e5c487bfSMatthew G. Knepley /* Get points */ 648707218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6488c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6489c459fbc1SJed Brown PetscInt dof; 64909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6491c459fbc1SJed Brown clsize += dof; 6492c459fbc1SJed Brown } 64939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6494e5c487bfSMatthew G. Knepley /* Filter points */ 6495e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6496e5c487bfSMatthew G. Knepley PetscInt dep; 6497e5c487bfSMatthew G. Knepley 64989566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6499e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6500e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6501e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6502e5c487bfSMatthew G. Knepley ++Np; 6503e5c487bfSMatthew G. Knepley } 6504e5c487bfSMatthew G. Knepley /* Get array */ 6505e5c487bfSMatthew G. Knepley if (!values || !*values) { 6506e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6507e5c487bfSMatthew G. Knepley 6508e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 65099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6510e5c487bfSMatthew G. Knepley asize += dof; 6511e5c487bfSMatthew G. Knepley } 6512e5c487bfSMatthew G. Knepley if (!values) { 65139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6514e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 65153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6516e5c487bfSMatthew G. Knepley } 65179566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6518e5c487bfSMatthew G. Knepley } else { 6519e5c487bfSMatthew G. Knepley array = *values; 6520e5c487bfSMatthew G. Knepley } 65219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6522e5c487bfSMatthew G. Knepley /* Get values */ 65239566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 65249566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6525e5c487bfSMatthew G. Knepley /* Cleanup points */ 65269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6527e5c487bfSMatthew G. Knepley /* Cleanup array */ 65289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6529e5c487bfSMatthew G. Knepley if (!*values) { 6530e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6531e5c487bfSMatthew G. Knepley *values = array; 6532e5c487bfSMatthew G. Knepley } else { 653363a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6534e5c487bfSMatthew G. Knepley *csize = size; 6535e5c487bfSMatthew G. Knepley } 65363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6537e5c487bfSMatthew G. Knepley } 6538e5c487bfSMatthew G. Knepley 6539552f7358SJed Brown /*@C 6540552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6541552f7358SJed Brown 6542552f7358SJed Brown Not collective 6543552f7358SJed Brown 6544552f7358SJed Brown Input Parameters: 6545a1cb98faSBarry Smith + dm - The `DM` 654620f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6547552f7358SJed Brown . v - The local vector 6548a1cb98faSBarry Smith . point - The point in the `DM` 654920f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6550552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6551552f7358SJed Brown 6552552f7358SJed Brown Level: intermediate 6553552f7358SJed Brown 6554a1cb98faSBarry Smith Note: 655520f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6556a1cb98faSBarry Smith 655760225df5SJacob Faibussowitsch Fortran Notes: 655820f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6559a1cb98faSBarry Smith 65601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6561552f7358SJed Brown @*/ 6562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6563d71ae5a4SJacob Faibussowitsch { 6564552f7358SJed Brown PetscInt size = 0; 6565552f7358SJed Brown 6566552f7358SJed Brown PetscFunctionBegin; 6567552f7358SJed Brown /* Should work without recalculating size */ 65689566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6569c9fdaa05SMatthew G. Knepley *values = NULL; 65703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6571552f7358SJed Brown } 6572552f7358SJed Brown 6573d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6574d71ae5a4SJacob Faibussowitsch { 65759371c9d4SSatish Balay *x += y; 65769371c9d4SSatish Balay } 6577d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6578d71ae5a4SJacob Faibussowitsch { 65799371c9d4SSatish Balay *x = y; 65809371c9d4SSatish Balay } 6581552f7358SJed Brown 6582d71ae5a4SJacob 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[]) 6583d71ae5a4SJacob Faibussowitsch { 6584552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6585552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6586552f7358SJed Brown PetscScalar *a; 6587552f7358SJed Brown PetscInt off, cind = 0, k; 6588552f7358SJed Brown 6589552f7358SJed Brown PetscFunctionBegin; 65909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6592552f7358SJed Brown a = &array[off]; 6593552f7358SJed Brown if (!cdof || setBC) { 659497e99dd9SToby Isaac if (clperm) { 65959371c9d4SSatish Balay if (perm) { 6596ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6597552f7358SJed Brown } else { 6598ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 65999371c9d4SSatish Balay } 66009371c9d4SSatish Balay } else { 66019371c9d4SSatish Balay if (perm) { 6602ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 66039371c9d4SSatish Balay } else { 6604ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 66059371c9d4SSatish Balay } 6606552f7358SJed Brown } 6607552f7358SJed Brown } else { 66089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 660997e99dd9SToby Isaac if (clperm) { 66109371c9d4SSatish Balay if (perm) { 66119371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 66129371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66139371c9d4SSatish Balay ++cind; 66149371c9d4SSatish Balay continue; 66159371c9d4SSatish Balay } 661697e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6617552f7358SJed Brown } 6618552f7358SJed Brown } else { 6619552f7358SJed Brown for (k = 0; k < dof; ++k) { 66209371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66219371c9d4SSatish Balay ++cind; 66229371c9d4SSatish Balay continue; 66239371c9d4SSatish Balay } 662497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 662597e99dd9SToby Isaac } 662697e99dd9SToby Isaac } 662797e99dd9SToby Isaac } else { 662897e99dd9SToby Isaac if (perm) { 662997e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66309371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66319371c9d4SSatish Balay ++cind; 66329371c9d4SSatish Balay continue; 66339371c9d4SSatish Balay } 663497e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 663597e99dd9SToby Isaac } 663697e99dd9SToby Isaac } else { 663797e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 66389371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 66399371c9d4SSatish Balay ++cind; 66409371c9d4SSatish Balay continue; 66419371c9d4SSatish Balay } 664297e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 664397e99dd9SToby Isaac } 6644552f7358SJed Brown } 6645552f7358SJed Brown } 6646552f7358SJed Brown } 66473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6648552f7358SJed Brown } 6649552f7358SJed Brown 6650d71ae5a4SJacob 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[]) 6651d71ae5a4SJacob Faibussowitsch { 6652a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6653a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6654a5e93ea8SMatthew G. Knepley PetscScalar *a; 6655a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6656a5e93ea8SMatthew G. Knepley 6657a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 66589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 66599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6660a5e93ea8SMatthew G. Knepley a = &array[off]; 6661a5e93ea8SMatthew G. Knepley if (cdof) { 66629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 666397e99dd9SToby Isaac if (clperm) { 666497e99dd9SToby Isaac if (perm) { 6665a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6666a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 666797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 666897e99dd9SToby Isaac cind++; 6669a5e93ea8SMatthew G. Knepley } 6670a5e93ea8SMatthew G. Knepley } 6671a5e93ea8SMatthew G. Knepley } else { 6672a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6673a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 667497e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 667597e99dd9SToby Isaac cind++; 667697e99dd9SToby Isaac } 667797e99dd9SToby Isaac } 667897e99dd9SToby Isaac } 667997e99dd9SToby Isaac } else { 668097e99dd9SToby Isaac if (perm) { 668197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668297e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 668397e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 668497e99dd9SToby Isaac cind++; 668597e99dd9SToby Isaac } 668697e99dd9SToby Isaac } 668797e99dd9SToby Isaac } else { 668897e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 668997e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 669097e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 669197e99dd9SToby Isaac cind++; 669297e99dd9SToby Isaac } 6693a5e93ea8SMatthew G. Knepley } 6694a5e93ea8SMatthew G. Knepley } 6695a5e93ea8SMatthew G. Knepley } 6696a5e93ea8SMatthew G. Knepley } 66973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6698a5e93ea8SMatthew G. Knepley } 6699a5e93ea8SMatthew G. Knepley 6700d71ae5a4SJacob 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[]) 6701d71ae5a4SJacob Faibussowitsch { 6702552f7358SJed Brown PetscScalar *a; 67031a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67041a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 670597e99dd9SToby Isaac PetscInt cind = 0, b; 6706552f7358SJed Brown 6707552f7358SJed Brown PetscFunctionBegin; 67089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67111a271a75SMatthew G. Knepley a = &array[foff]; 6712552f7358SJed Brown if (!fcdof || setBC) { 671397e99dd9SToby Isaac if (clperm) { 67149371c9d4SSatish Balay if (perm) { 6715ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6716552f7358SJed Brown } else { 6717ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 67189371c9d4SSatish Balay } 67199371c9d4SSatish Balay } else { 67209371c9d4SSatish Balay if (perm) { 6721ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 67229371c9d4SSatish Balay } else { 6723ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 67249371c9d4SSatish Balay } 6725552f7358SJed Brown } 6726552f7358SJed Brown } else { 67279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 672897e99dd9SToby Isaac if (clperm) { 672997e99dd9SToby Isaac if (perm) { 673097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67319371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67329371c9d4SSatish Balay ++cind; 67339371c9d4SSatish Balay continue; 67349371c9d4SSatish Balay } 673597e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6736552f7358SJed Brown } 6737552f7358SJed Brown } else { 673897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67399371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67409371c9d4SSatish Balay ++cind; 67419371c9d4SSatish Balay continue; 67429371c9d4SSatish Balay } 674397e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 674497e99dd9SToby Isaac } 674597e99dd9SToby Isaac } 674697e99dd9SToby Isaac } else { 674797e99dd9SToby Isaac if (perm) { 674897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67499371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67509371c9d4SSatish Balay ++cind; 67519371c9d4SSatish Balay continue; 67529371c9d4SSatish Balay } 675397e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 675497e99dd9SToby Isaac } 675597e99dd9SToby Isaac } else { 675697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 67579371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67589371c9d4SSatish Balay ++cind; 67599371c9d4SSatish Balay continue; 67609371c9d4SSatish Balay } 676197e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6762552f7358SJed Brown } 6763552f7358SJed Brown } 6764552f7358SJed Brown } 6765552f7358SJed Brown } 67661a271a75SMatthew G. Knepley *offset += fdof; 67673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6768552f7358SJed Brown } 6769552f7358SJed Brown 6770d71ae5a4SJacob 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[]) 6771d71ae5a4SJacob Faibussowitsch { 6772a5e93ea8SMatthew G. Knepley PetscScalar *a; 67731a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 67741a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67755da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6776ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6777a5e93ea8SMatthew G. Knepley 6778a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67831a271a75SMatthew G. Knepley a = &array[foff]; 6784a5e93ea8SMatthew G. Knepley if (fcdof) { 6785ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 678797e99dd9SToby Isaac if (clperm) { 678897e99dd9SToby Isaac if (perm) { 6789ba322698SMatthew G. Knepley if (comps) { 6790ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6791ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67929371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67939371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67949371c9d4SSatish Balay ncSet = PETSC_TRUE; 67959371c9d4SSatish Balay } 67969371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67979371c9d4SSatish Balay ++cind; 67989371c9d4SSatish Balay fcSet = PETSC_TRUE; 67999371c9d4SSatish Balay } 6800ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6801ba322698SMatthew G. Knepley } 6802ba322698SMatthew G. Knepley } else { 680397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 680497e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 680597e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6806a5e93ea8SMatthew G. Knepley ++cind; 6807a5e93ea8SMatthew G. Knepley } 6808a5e93ea8SMatthew G. Knepley } 6809ba322698SMatthew G. Knepley } 6810ba322698SMatthew G. Knepley } else { 6811ba322698SMatthew G. Knepley if (comps) { 6812ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6813ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68149371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68159371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68169371c9d4SSatish Balay ncSet = PETSC_TRUE; 68179371c9d4SSatish Balay } 68189371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68199371c9d4SSatish Balay ++cind; 68209371c9d4SSatish Balay fcSet = PETSC_TRUE; 68219371c9d4SSatish Balay } 6822ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6823ba322698SMatthew G. Knepley } 6824a5e93ea8SMatthew G. Knepley } else { 682597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 682697e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 682797e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 682897e99dd9SToby Isaac ++cind; 682997e99dd9SToby Isaac } 683097e99dd9SToby Isaac } 683197e99dd9SToby Isaac } 6832ba322698SMatthew G. Knepley } 683397e99dd9SToby Isaac } else { 683497e99dd9SToby Isaac if (perm) { 6835ba322698SMatthew G. Knepley if (comps) { 6836ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6837ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68389371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68399371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68409371c9d4SSatish Balay ncSet = PETSC_TRUE; 68419371c9d4SSatish Balay } 68429371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68439371c9d4SSatish Balay ++cind; 68449371c9d4SSatish Balay fcSet = PETSC_TRUE; 68459371c9d4SSatish Balay } 6846ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6847ba322698SMatthew G. Knepley } 6848ba322698SMatthew G. Knepley } else { 684997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 685097e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 685197e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 685297e99dd9SToby Isaac ++cind; 685397e99dd9SToby Isaac } 685497e99dd9SToby Isaac } 6855ba322698SMatthew G. Knepley } 6856ba322698SMatthew G. Knepley } else { 6857ba322698SMatthew G. Knepley if (comps) { 6858ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6859ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 68609371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 68619371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 68629371c9d4SSatish Balay ncSet = PETSC_TRUE; 68639371c9d4SSatish Balay } 68649371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68659371c9d4SSatish Balay ++cind; 68669371c9d4SSatish Balay fcSet = PETSC_TRUE; 68679371c9d4SSatish Balay } 6868ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6869ba322698SMatthew G. Knepley } 687097e99dd9SToby Isaac } else { 687197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 687297e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 687397e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6874a5e93ea8SMatthew G. Knepley ++cind; 6875a5e93ea8SMatthew G. Knepley } 6876a5e93ea8SMatthew G. Knepley } 6877a5e93ea8SMatthew G. Knepley } 6878a5e93ea8SMatthew G. Knepley } 6879a5e93ea8SMatthew G. Knepley } 6880ba322698SMatthew G. Knepley } 68811a271a75SMatthew G. Knepley *offset += fdof; 68823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6883a5e93ea8SMatthew G. Knepley } 6884a5e93ea8SMatthew G. Knepley 6885d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6886d71ae5a4SJacob Faibussowitsch { 6887552f7358SJed Brown PetscScalar *array; 68881b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68891b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6890552f7358SJed Brown 68911b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68949566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68969566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6897b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6898b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6899b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6900b6ebb6e6SMatthew G. Knepley 69019371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 69029371c9d4SSatish Balay dof = 0; 69039371c9d4SSatish Balay continue; 69049371c9d4SSatish Balay } 69059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6906b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6907b6ebb6e6SMatthew G. Knepley { 6908b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6909b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6910b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6911b6ebb6e6SMatthew G. Knepley 69129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 69139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6914b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6915b6ebb6e6SMatthew G. Knepley if (!cdof) { 6916b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6917ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6918b6ebb6e6SMatthew G. Knepley } else { 6919ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6920b6ebb6e6SMatthew G. Knepley } 6921b6ebb6e6SMatthew G. Knepley } else { 69229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6923b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6924b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69259371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69269371c9d4SSatish Balay ++cind; 69279371c9d4SSatish Balay continue; 69289371c9d4SSatish Balay } 6929b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6930b6ebb6e6SMatthew G. Knepley } 6931b6ebb6e6SMatthew G. Knepley } else { 6932b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 69339371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 69349371c9d4SSatish Balay ++cind; 69359371c9d4SSatish Balay continue; 69369371c9d4SSatish Balay } 6937b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6938b6ebb6e6SMatthew G. Knepley } 6939b6ebb6e6SMatthew G. Knepley } 6940b6ebb6e6SMatthew G. Knepley } 6941b6ebb6e6SMatthew G. Knepley } 6942b6ebb6e6SMatthew G. Knepley } 69439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 69443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6945b6ebb6e6SMatthew G. Knepley } 69461b406b76SMatthew G. Knepley 69471b406b76SMatthew G. Knepley /*@C 694820f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 69491b406b76SMatthew G. Knepley 69501b406b76SMatthew G. Knepley Not collective 69511b406b76SMatthew G. Knepley 69521b406b76SMatthew G. Knepley Input Parameters: 6953a1cb98faSBarry Smith + dm - The `DM` 695420f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 69551b406b76SMatthew G. Knepley . v - The local vector 695620f4b53cSBarry Smith . point - The point in the `DM` 69571b406b76SMatthew G. Knepley . values - The array of values 6958a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6959a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 69601b406b76SMatthew G. Knepley 69611b406b76SMatthew G. Knepley Level: intermediate 69621b406b76SMatthew G. Knepley 69631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 69641b406b76SMatthew G. Knepley @*/ 6965d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6966d71ae5a4SJacob Faibussowitsch { 69671b406b76SMatthew G. Knepley PetscSection clSection; 69681b406b76SMatthew G. Knepley IS clPoints; 69691b406b76SMatthew G. Knepley PetscScalar *array; 69701b406b76SMatthew G. Knepley PetscInt *points = NULL; 697127f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6972c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 69731b406b76SMatthew G. Knepley 69741a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69751b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69769566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69771a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69781a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69811b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69829566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69841b406b76SMatthew G. Knepley } 69851a271a75SMatthew G. Knepley /* Get points */ 698607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6987c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6988c459fbc1SJed Brown PetscInt dof; 69899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6990c459fbc1SJed Brown clsize += dof; 6991c459fbc1SJed Brown } 69929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69931a271a75SMatthew G. Knepley /* Get array */ 69949566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69951a271a75SMatthew G. Knepley /* Get values */ 6996ef90cfe2SMatthew G. Knepley if (numFields > 0) { 699797e99dd9SToby Isaac PetscInt offset = 0, f; 6998552f7358SJed Brown for (f = 0; f < numFields; ++f) { 699997e99dd9SToby Isaac const PetscInt **perms = NULL; 700097e99dd9SToby Isaac const PetscScalar **flips = NULL; 700197e99dd9SToby Isaac 70029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7003552f7358SJed Brown switch (mode) { 7004552f7358SJed Brown case INSERT_VALUES: 700597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 700697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70093ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 70109371c9d4SSatish Balay } 70119371c9d4SSatish Balay break; 7012552f7358SJed Brown case INSERT_ALL_VALUES: 701397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 701497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70173ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 70189371c9d4SSatish Balay } 70199371c9d4SSatish Balay break; 7020a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 702197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 702297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70253ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 70269371c9d4SSatish Balay } 70279371c9d4SSatish Balay break; 7028552f7358SJed Brown case ADD_VALUES: 702997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70333ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 70349371c9d4SSatish Balay } 70359371c9d4SSatish Balay break; 7036552f7358SJed Brown case ADD_ALL_VALUES: 703797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 703897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70413ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 70429371c9d4SSatish Balay } 70439371c9d4SSatish Balay break; 7044304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 704597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 704697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 704797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 704897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70493ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 70509371c9d4SSatish Balay } 70519371c9d4SSatish Balay break; 7052d71ae5a4SJacob Faibussowitsch default: 7053d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7054552f7358SJed Brown } 70559566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 70561a271a75SMatthew G. Knepley } 7057552f7358SJed Brown } else { 70581a271a75SMatthew G. Knepley PetscInt dof, off; 705997e99dd9SToby Isaac const PetscInt **perms = NULL; 706097e99dd9SToby Isaac const PetscScalar **flips = NULL; 70611a271a75SMatthew G. Knepley 70629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7063552f7358SJed Brown switch (mode) { 7064552f7358SJed Brown case INSERT_VALUES: 706597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 706697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 706797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 706897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70703ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70719371c9d4SSatish Balay } 70729371c9d4SSatish Balay break; 7073552f7358SJed Brown case INSERT_ALL_VALUES: 707497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 707597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 707697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 707797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70793ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70809371c9d4SSatish Balay } 70819371c9d4SSatish Balay break; 7082a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 708397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 708497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 708597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 708697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70883ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70899371c9d4SSatish Balay } 70909371c9d4SSatish Balay break; 7091552f7358SJed Brown case ADD_VALUES: 709297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 709397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 709497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 709597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70973ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70989371c9d4SSatish Balay } 70999371c9d4SSatish Balay break; 7100552f7358SJed Brown case ADD_ALL_VALUES: 710197e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 710297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 710397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 710497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71063ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 71079371c9d4SSatish Balay } 71089371c9d4SSatish Balay break; 7109304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 711097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 711197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 711297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 711397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 71153ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 71169371c9d4SSatish Balay } 71179371c9d4SSatish Balay break; 7118d71ae5a4SJacob Faibussowitsch default: 7119d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7120552f7358SJed Brown } 71219566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7122552f7358SJed Brown } 71231a271a75SMatthew G. Knepley /* Cleanup points */ 71249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 71251a271a75SMatthew G. Knepley /* Cleanup array */ 71269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7128552f7358SJed Brown } 7129552f7358SJed Brown 71305f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7131d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7132d71ae5a4SJacob Faibussowitsch { 71335f790a90SMatthew G. Knepley PetscFunctionBegin; 713411cc89d2SBarry Smith *contains = PETSC_TRUE; 71355f790a90SMatthew G. Knepley if (label) { 7136d6177c40SToby Isaac PetscInt fdof; 71375f790a90SMatthew G. Knepley 713811cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 713911cc89d2SBarry Smith if (!*contains) { 71409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 71415f790a90SMatthew G. Knepley *offset += fdof; 71423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71435f790a90SMatthew G. Knepley } 71445f790a90SMatthew G. Knepley } 71453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71465f790a90SMatthew G. Knepley } 71475f790a90SMatthew G. Knepley 714897529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7149d71ae5a4SJacob 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) 7150d71ae5a4SJacob Faibussowitsch { 7151e07394fbSMatthew G. Knepley PetscSection clSection; 7152e07394fbSMatthew G. Knepley IS clPoints; 7153e07394fbSMatthew G. Knepley PetscScalar *array; 7154e07394fbSMatthew G. Knepley PetscInt *points = NULL; 715597529cf3SJed Brown const PetscInt *clp; 7156e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 715797e99dd9SToby Isaac PetscInt offset = 0, f; 7158e07394fbSMatthew G. Knepley 7159e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7160e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71619566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7162e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7163e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7165e07394fbSMatthew G. Knepley /* Get points */ 716607218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7167e07394fbSMatthew G. Knepley /* Get array */ 71689566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7169e07394fbSMatthew G. Knepley /* Get values */ 7170e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 717197e99dd9SToby Isaac const PetscInt **perms = NULL; 717297e99dd9SToby Isaac const PetscScalar **flips = NULL; 717311cc89d2SBarry Smith PetscBool contains; 717497e99dd9SToby Isaac 7175e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7176e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7177e07394fbSMatthew G. Knepley PetscInt fdof; 71789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7179e07394fbSMatthew G. Knepley offset += fdof; 7180e07394fbSMatthew G. Knepley } 7181e07394fbSMatthew G. Knepley continue; 7182e07394fbSMatthew G. Knepley } 71839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7184e07394fbSMatthew G. Knepley switch (mode) { 7185e07394fbSMatthew G. Knepley case INSERT_VALUES: 718697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 718797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 718897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 718997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 719011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 719111cc89d2SBarry Smith if (!contains) continue; 71929566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71939371c9d4SSatish Balay } 71949371c9d4SSatish Balay break; 7195e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 719697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 719797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 719997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 720011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 720111cc89d2SBarry Smith if (!contains) continue; 72029566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 72039371c9d4SSatish Balay } 72049371c9d4SSatish Balay break; 7205e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 720697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 720797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 721011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 721111cc89d2SBarry Smith if (!contains) continue; 72129566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 72139371c9d4SSatish Balay } 72149371c9d4SSatish Balay break; 7215e07394fbSMatthew G. Knepley case ADD_VALUES: 721697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 721797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 722011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 722111cc89d2SBarry Smith if (!contains) continue; 72229566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 72239371c9d4SSatish Balay } 72249371c9d4SSatish Balay break; 7225e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 722697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 722797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 723011cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 723111cc89d2SBarry Smith if (!contains) continue; 72329566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 72339371c9d4SSatish Balay } 72349371c9d4SSatish Balay break; 7235d71ae5a4SJacob Faibussowitsch default: 7236d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7237e07394fbSMatthew G. Knepley } 72389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7239e07394fbSMatthew G. Knepley } 7240e07394fbSMatthew G. Knepley /* Cleanup points */ 72419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7242e07394fbSMatthew G. Knepley /* Cleanup array */ 72439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7245e07394fbSMatthew G. Knepley } 7246e07394fbSMatthew G. Knepley 7247d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7248d71ae5a4SJacob Faibussowitsch { 7249552f7358SJed Brown PetscMPIInt rank; 7250552f7358SJed Brown PetscInt i, j; 7251552f7358SJed Brown 7252552f7358SJed Brown PetscFunctionBegin; 72539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 725463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 725563a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 725663a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7257b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 72583ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7259b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 72609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7261b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7262519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 72639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7264552f7358SJed Brown #else 72659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7266552f7358SJed Brown #endif 7267552f7358SJed Brown } 72689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7269552f7358SJed Brown } 72703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7271552f7358SJed Brown } 7272552f7358SJed Brown 727305586334SMatthew G. Knepley /* 727405586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 727505586334SMatthew G. Knepley 727605586334SMatthew G. Knepley Input Parameters: 727705586334SMatthew G. Knepley + section - The section for this data layout 727836fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 727905586334SMatthew G. Knepley . point - The point contributing dofs with these indices 728005586334SMatthew G. Knepley . off - The global offset of this point 728105586334SMatthew G. Knepley . loff - The local offset of each field 7282a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 728305586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 728405586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 728505586334SMatthew G. Knepley 728605586334SMatthew G. Knepley Output Parameter: 728705586334SMatthew G. Knepley . indices - Indices for dofs on this point 728805586334SMatthew G. Knepley 728905586334SMatthew G. Knepley Level: developer 729005586334SMatthew G. Knepley 729105586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 729205586334SMatthew G. Knepley */ 7293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7294d71ae5a4SJacob Faibussowitsch { 7295e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7296552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7297552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7298552f7358SJed Brown PetscInt cind = 0, k; 7299552f7358SJed Brown 7300552f7358SJed Brown PetscFunctionBegin; 730108401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 73039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7304552f7358SJed Brown if (!cdof || setBC) { 730505586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 730605586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 730705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 730805586334SMatthew G. Knepley 730905586334SMatthew G. Knepley indices[ind] = off + k; 7310552f7358SJed Brown } 7311552f7358SJed Brown } else { 73129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 73134acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 731405586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 731505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731605586334SMatthew G. Knepley 73174acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 73184acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 731905586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 73204acb8e1eSToby Isaac ++cind; 73214acb8e1eSToby Isaac } else { 732236fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7323552f7358SJed Brown } 7324552f7358SJed Brown } 7325552f7358SJed Brown } 7326e6ccafaeSMatthew G Knepley *loff += dof; 73273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7328552f7358SJed Brown } 7329552f7358SJed Brown 73307e29afd2SMatthew G. Knepley /* 733136fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 73327e29afd2SMatthew G. Knepley 733336fa2b79SJed Brown Input Parameters: 733436fa2b79SJed Brown + section - a section (global or local) 733520f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 733636fa2b79SJed Brown . point - point within section 733736fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 733836fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 733936fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 734036fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 734136fa2b79SJed Brown . permsoff - offset 734236fa2b79SJed Brown - indperm - index permutation 734336fa2b79SJed Brown 734436fa2b79SJed Brown Output Parameter: 734536fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 734636fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 734736fa2b79SJed Brown 734836fa2b79SJed Brown Notes: 734936fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 735036fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 735136fa2b79SJed Brown in the local vector. 735236fa2b79SJed Brown 735336fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 735436fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 735536fa2b79SJed Brown 735636fa2b79SJed Brown Developer Note: 735736fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 735836fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 735936fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 736036fa2b79SJed Brown 736136fa2b79SJed Brown Example: 736236fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 736336fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 736436fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 736536fa2b79SJed 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. 736636fa2b79SJed Brown 736736fa2b79SJed Brown Level: developer 73687e29afd2SMatthew G. Knepley */ 7369d71ae5a4SJacob 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[]) 7370d71ae5a4SJacob Faibussowitsch { 7371552f7358SJed Brown PetscInt numFields, foff, f; 7372552f7358SJed Brown 7373552f7358SJed Brown PetscFunctionBegin; 737408401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7376552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73774acb8e1eSToby Isaac PetscInt fdof, cfdof; 7378552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73794acb8e1eSToby Isaac PetscInt cind = 0, b; 73804acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7381552f7358SJed Brown 73829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7384552f7358SJed Brown if (!cfdof || setBC) { 738505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 738605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 738705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 738805586334SMatthew G. Knepley 738905586334SMatthew G. Knepley indices[ind] = off + foff + b; 739005586334SMatthew G. Knepley } 7391552f7358SJed Brown } else { 73929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 739305586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 739405586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 739505586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 739605586334SMatthew G. Knepley 73974acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 739805586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7399552f7358SJed Brown ++cind; 7400552f7358SJed Brown } else { 740136fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7402552f7358SJed Brown } 7403552f7358SJed Brown } 7404552f7358SJed Brown } 740536fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7406552f7358SJed Brown foffs[f] += fdof; 7407552f7358SJed Brown } 74083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7409552f7358SJed Brown } 7410552f7358SJed Brown 74117e29afd2SMatthew G. Knepley /* 74127e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 74137e29afd2SMatthew G. Knepley 74147e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7415645102dcSJed Brown 7416645102dcSJed Brown Notes: 7417645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7418645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 74197e29afd2SMatthew G. Knepley */ 7420d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7421d71ae5a4SJacob Faibussowitsch { 74227e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 74237e29afd2SMatthew G. Knepley 74247e29afd2SMatthew G. Knepley PetscFunctionBegin; 74259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 74267e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 74277e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 74287e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 74297e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 74307e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 74317e29afd2SMatthew G. Knepley 74329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 74339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 74349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7435645102dcSJed Brown if (!cfdof) { 743605586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 743705586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 743805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 743905586334SMatthew G. Knepley 744005586334SMatthew G. Knepley indices[ind] = foff + b; 744105586334SMatthew G. Knepley } 74427e29afd2SMatthew G. Knepley } else { 74439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 744405586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 744505586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 744605586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744705586334SMatthew G. Knepley 74487e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 744905586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 74507e29afd2SMatthew G. Knepley ++cind; 74517e29afd2SMatthew G. Knepley } else { 745205586334SMatthew G. Knepley indices[ind] = foff + b - cind; 74537e29afd2SMatthew G. Knepley } 74547e29afd2SMatthew G. Knepley } 74557e29afd2SMatthew G. Knepley } 74567e29afd2SMatthew G. Knepley foffs[f] += fdof; 74577e29afd2SMatthew G. Knepley } 74583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74597e29afd2SMatthew G. Knepley } 74607e29afd2SMatthew G. Knepley 7461d71ae5a4SJacob 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) 7462d71ae5a4SJacob Faibussowitsch { 7463d3d1a6afSToby Isaac Mat cMat; 7464d3d1a6afSToby Isaac PetscSection aSec, cSec; 7465d3d1a6afSToby Isaac IS aIS; 7466d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7467d3d1a6afSToby Isaac const PetscInt *anchors; 7468e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7469d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7470d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7471d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7472d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7473d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7474d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7475d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 74766ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7477d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7478d3d1a6afSToby Isaac 7479d3d1a6afSToby Isaac PetscFunctionBegin; 7480d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7481d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 74829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7483d3d1a6afSToby Isaac 74849566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7485d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7486d3d1a6afSToby Isaac if (aSec) { 74879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 74889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 74899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7490d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7491d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7492d3d1a6afSToby Isaac * into the global matrix anyway) */ 7493d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7494d3d1a6afSToby Isaac PetscInt b = points[p]; 74954b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7496d3d1a6afSToby Isaac 74979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7498ad540459SPierre Jolivet if (!bSecDof) continue; 749948a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7500d3d1a6afSToby Isaac if (bDof) { 7501d3d1a6afSToby Isaac /* this point is constrained */ 7502d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7503d3d1a6afSToby Isaac PetscInt bOff, q; 7504d3d1a6afSToby Isaac 7505d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7506d3d1a6afSToby Isaac newNumPoints += bDof; 75079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7508d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7509d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7510d3d1a6afSToby Isaac PetscInt aDof; 7511d3d1a6afSToby Isaac 75129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7513d3d1a6afSToby Isaac newNumIndices += aDof; 7514d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7515d3d1a6afSToby Isaac PetscInt fDof; 7516d3d1a6afSToby Isaac 75179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7518d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7519d3d1a6afSToby Isaac } 7520d3d1a6afSToby Isaac } 75219371c9d4SSatish Balay } else { 7522d3d1a6afSToby Isaac /* this point is not constrained */ 7523d3d1a6afSToby Isaac newNumPoints++; 75244b2f2278SToby Isaac newNumIndices += bSecDof; 7525d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7526d3d1a6afSToby Isaac PetscInt fDof; 7527d3d1a6afSToby Isaac 75289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7529d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7530d3d1a6afSToby Isaac } 7531d3d1a6afSToby Isaac } 7532d3d1a6afSToby Isaac } 7533d3d1a6afSToby Isaac } 7534d3d1a6afSToby Isaac if (!anyConstrained) { 753572b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 753672b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 753772b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 753872b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 75399566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7541d3d1a6afSToby Isaac } 7542d3d1a6afSToby Isaac 75436ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 75446ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 75456ecaa68aSToby Isaac 7546f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7547d3d1a6afSToby Isaac 75486ecaa68aSToby Isaac if (!outPoints && !outValues) { 75496ecaa68aSToby Isaac if (offsets) { 7550ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 75516ecaa68aSToby Isaac } 75529566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 75533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75546ecaa68aSToby Isaac } 75556ecaa68aSToby Isaac 75561dca8a05SBarry 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); 7557d3d1a6afSToby Isaac 75589566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7559d3d1a6afSToby Isaac 7560d3d1a6afSToby Isaac /* workspaces */ 7561d3d1a6afSToby Isaac if (numFields) { 7562d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 75639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 75649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7565d3d1a6afSToby Isaac } 75669371c9d4SSatish Balay } else { 75679566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 75689566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7569d3d1a6afSToby Isaac } 7570d3d1a6afSToby Isaac 7571d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7572d3d1a6afSToby Isaac if (numFields) { 75734b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 75744b2f2278SToby Isaac 7575d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7576d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 75774b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7578d3d1a6afSToby Isaac 75799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75804b2f2278SToby Isaac if (!bSecDof) { 75814b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 75824b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 75834b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 75844b2f2278SToby Isaac } 75854b2f2278SToby Isaac continue; 75864b2f2278SToby Isaac } 758748a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7588d3d1a6afSToby Isaac if (bDof) { 7589d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7590d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7591d3d1a6afSToby Isaac 75929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 75939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7594d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7595d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7596d3d1a6afSToby Isaac PetscInt aFDof; 7597d3d1a6afSToby Isaac 75989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7599d3d1a6afSToby Isaac allFDof += aFDof; 7600d3d1a6afSToby Isaac } 7601d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7602d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7603d3d1a6afSToby Isaac } 76049371c9d4SSatish Balay } else { 7605d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7606d3d1a6afSToby Isaac PetscInt fDof; 7607d3d1a6afSToby Isaac 76089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7609d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7610d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7611d3d1a6afSToby Isaac } 7612d3d1a6afSToby Isaac } 7613d3d1a6afSToby Isaac } 76144b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 76154b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 76164b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7617d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7618d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7619d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7620d3d1a6afSToby Isaac } 762119f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 762219f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 76239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7624d3d1a6afSToby Isaac } 76259371c9d4SSatish Balay } else { 7626d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7627d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 76284b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7629d3d1a6afSToby Isaac 76309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 76314b2f2278SToby Isaac if (!bSecDof) { 76324b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 76334b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 76344b2f2278SToby Isaac continue; 76354b2f2278SToby Isaac } 763648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7637d3d1a6afSToby Isaac if (bDof) { 76384b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7639d3d1a6afSToby Isaac 76409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7641d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7642d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7643d3d1a6afSToby Isaac 76449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7645d3d1a6afSToby Isaac allDof += aDof; 7646d3d1a6afSToby Isaac } 7647d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 76484b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 76499371c9d4SSatish Balay } else { 76504b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7651d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7652d3d1a6afSToby Isaac } 7653d3d1a6afSToby Isaac } 7654d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7655d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7656d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7657d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7658d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7659d3d1a6afSToby Isaac } 76609566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7661d3d1a6afSToby Isaac } 7662d3d1a6afSToby Isaac 76636ecaa68aSToby Isaac /* output arrays */ 76649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 76656ecaa68aSToby Isaac 7666d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 76679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 76689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 76699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 76709566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7671d3d1a6afSToby Isaac if (numFields) { 7672d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7673d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7674d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 76754b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7676d3d1a6afSToby Isaac 76779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7678ad540459SPierre Jolivet if (!bSecDof) continue; 767948a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7680d3d1a6afSToby Isaac if (bDof) { 7681d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7682d3d1a6afSToby Isaac 7683d3d1a6afSToby Isaac fStart[0] = 0; 7684d3d1a6afSToby Isaac fEnd[0] = 0; 7685d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7686d3d1a6afSToby Isaac PetscInt fDof; 7687d3d1a6afSToby Isaac 76889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7689d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7690d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7691d3d1a6afSToby Isaac } 76929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76939566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7694d3d1a6afSToby Isaac 7695d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7696d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7697d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7698d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7699d3d1a6afSToby Isaac 7700d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7701d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7702d3d1a6afSToby Isaac } 77039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7704d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7705d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7706d3d1a6afSToby Isaac 7707d3d1a6afSToby 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 */ 7708d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7709d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77119566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7712d3d1a6afSToby Isaac } 7713d3d1a6afSToby Isaac newP += bDof; 7714d3d1a6afSToby Isaac 77156ecaa68aSToby Isaac if (outValues) { 7716d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 771748a46eb9SPierre 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])); 7718d3d1a6afSToby Isaac } 77199371c9d4SSatish Balay } else { 7720d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7721d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7722d3d1a6afSToby Isaac newP++; 7723d3d1a6afSToby Isaac } 7724d3d1a6afSToby Isaac } 7725d3d1a6afSToby Isaac } else { 7726d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7727d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7728d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 77294b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7730d3d1a6afSToby Isaac 77319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7732ad540459SPierre Jolivet if (!bSecDof) continue; 773348a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7734d3d1a6afSToby Isaac if (bDof) { 7735d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7736d3d1a6afSToby Isaac 77379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 77389566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7739d3d1a6afSToby Isaac 77409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7741d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7742d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7743d3d1a6afSToby Isaac 7744d3d1a6afSToby 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 */ 7745d3d1a6afSToby Isaac 7746d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7747d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 77489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 77499566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7750d3d1a6afSToby Isaac } 7751d3d1a6afSToby Isaac newP += bDof; 7752d3d1a6afSToby Isaac 7753d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 775448a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 77559371c9d4SSatish Balay } else { 7756d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7757d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7758d3d1a6afSToby Isaac newP++; 7759d3d1a6afSToby Isaac } 7760d3d1a6afSToby Isaac } 7761d3d1a6afSToby Isaac } 7762d3d1a6afSToby Isaac 77636ecaa68aSToby Isaac if (outValues) { 77649566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 77659566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7766d3d1a6afSToby Isaac /* multiply constraints on the right */ 7767d3d1a6afSToby Isaac if (numFields) { 7768d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7769d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7770d3d1a6afSToby Isaac 7771d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7772d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7773d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7774d3d1a6afSToby Isaac PetscInt c, r, k; 7775d3d1a6afSToby Isaac PetscInt dof; 7776d3d1a6afSToby Isaac 77779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7778ad540459SPierre Jolivet if (!dof) continue; 7779d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7780d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7781d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7782d3d1a6afSToby Isaac 7783d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7784d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7785ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7786d3d1a6afSToby Isaac } 7787d3d1a6afSToby Isaac } 77889371c9d4SSatish Balay } else { 7789d3d1a6afSToby Isaac /* copy this column as is */ 7790d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7791ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7792d3d1a6afSToby Isaac } 7793d3d1a6afSToby Isaac } 7794d3d1a6afSToby Isaac oldOff += dof; 7795d3d1a6afSToby Isaac } 7796d3d1a6afSToby Isaac } 77979371c9d4SSatish Balay } else { 7798d3d1a6afSToby Isaac PetscInt oldOff = 0; 7799d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7800d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7801d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7802d3d1a6afSToby Isaac PetscInt c, r, k; 7803d3d1a6afSToby Isaac PetscInt dof; 7804d3d1a6afSToby Isaac 78059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7806ad540459SPierre Jolivet if (!dof) continue; 7807d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7808d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7809d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7810d3d1a6afSToby Isaac 7811d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7812d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7813ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7814d3d1a6afSToby Isaac } 7815d3d1a6afSToby Isaac } 78169371c9d4SSatish Balay } else { 7817d3d1a6afSToby Isaac /* copy this column as is */ 7818d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7819ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7820d3d1a6afSToby Isaac } 7821d3d1a6afSToby Isaac } 7822d3d1a6afSToby Isaac oldOff += dof; 7823d3d1a6afSToby Isaac } 7824d3d1a6afSToby Isaac } 7825d3d1a6afSToby Isaac 78266ecaa68aSToby Isaac if (multiplyLeft) { 78279566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 78289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7829d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7830d3d1a6afSToby Isaac if (numFields) { 7831d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7832d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7833d3d1a6afSToby Isaac 7834d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7835d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7836d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7837d3d1a6afSToby Isaac PetscInt c, r, k; 7838d3d1a6afSToby Isaac PetscInt dof; 7839d3d1a6afSToby Isaac 78409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7841d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7842d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7843d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7844d3d1a6afSToby Isaac 7845d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7846d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7847ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7848d3d1a6afSToby Isaac } 7849d3d1a6afSToby Isaac } 78509371c9d4SSatish Balay } else { 7851d3d1a6afSToby Isaac /* copy this row as is */ 7852d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7853ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7854d3d1a6afSToby Isaac } 7855d3d1a6afSToby Isaac } 7856d3d1a6afSToby Isaac oldOff += dof; 7857d3d1a6afSToby Isaac } 7858d3d1a6afSToby Isaac } 78599371c9d4SSatish Balay } else { 7860d3d1a6afSToby Isaac PetscInt oldOff = 0; 7861d3d1a6afSToby Isaac 7862d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7863d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7864d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7865d3d1a6afSToby Isaac PetscInt c, r, k; 7866d3d1a6afSToby Isaac PetscInt dof; 7867d3d1a6afSToby Isaac 78689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7869d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7870d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7871d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7872d3d1a6afSToby Isaac 7873d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7874d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7875ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7876d3d1a6afSToby Isaac } 7877d3d1a6afSToby Isaac } 78789371c9d4SSatish Balay } else { 7879d3d1a6afSToby Isaac /* copy this row as is */ 78809fc93327SToby Isaac for (r = 0; r < dof; r++) { 7881ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7882d3d1a6afSToby Isaac } 7883d3d1a6afSToby Isaac } 7884d3d1a6afSToby Isaac oldOff += dof; 7885d3d1a6afSToby Isaac } 7886d3d1a6afSToby Isaac } 7887d3d1a6afSToby Isaac 78889566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 78899371c9d4SSatish Balay } else { 78906ecaa68aSToby Isaac newValues = tmpValues; 78916ecaa68aSToby Isaac } 78926ecaa68aSToby Isaac } 78936ecaa68aSToby Isaac 7894d3d1a6afSToby Isaac /* clean up */ 78959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 78969566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 78976ecaa68aSToby Isaac 7898d3d1a6afSToby Isaac if (numFields) { 7899d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 79009566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 79019566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 79029566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7903d3d1a6afSToby Isaac } 79049371c9d4SSatish Balay } else { 79059566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 79069566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 79079566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7908d3d1a6afSToby Isaac } 79099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7910d3d1a6afSToby Isaac 7911d3d1a6afSToby Isaac /* output */ 79126ecaa68aSToby Isaac if (outPoints) { 7913d3d1a6afSToby Isaac *outPoints = newPoints; 79149371c9d4SSatish Balay } else { 79159566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 79166ecaa68aSToby Isaac } 7917ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7918ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 79193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7920d3d1a6afSToby Isaac } 7921d3d1a6afSToby Isaac 79224a1e0b3eSMatthew G. Knepley /*@C 792371f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 79247cd05799SMatthew G. Knepley 79257cd05799SMatthew G. Knepley Not collective 79267cd05799SMatthew G. Knepley 79277cd05799SMatthew G. Knepley Input Parameters: 7928a1cb98faSBarry Smith + dm - The `DM` 7929a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7930a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 793171f0bbf9SMatthew G. Knepley . point - The point defining the closure 793271f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 79337cd05799SMatthew G. Knepley 793471f0bbf9SMatthew G. Knepley Output Parameters: 793571f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 793671f0bbf9SMatthew G. Knepley . indices - The dof indices 793720f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 793820f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 79397cd05799SMatthew G. Knepley 7940a1cb98faSBarry Smith Level: advanced 794136fa2b79SJed Brown 7942a1cb98faSBarry Smith Notes: 7943a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7944a1cb98faSBarry Smith 794520f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 794620f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 794736fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 794820f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 794936fa2b79SJed Brown indices (with the above semantics) are implied. 79507cd05799SMatthew G. Knepley 79511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7952a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 79534a1e0b3eSMatthew G. Knepley @*/ 7954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7955d71ae5a4SJacob Faibussowitsch { 795671f0bbf9SMatthew G. Knepley /* Closure ordering */ 79577773e69fSMatthew G. Knepley PetscSection clSection; 79587773e69fSMatthew G. Knepley IS clPoints; 795971f0bbf9SMatthew G. Knepley const PetscInt *clp; 796071f0bbf9SMatthew G. Knepley PetscInt *points; 796171f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 796271f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 79634acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 796471f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 796571f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 796671f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 796771f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 796871f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 796971f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 797071f0bbf9SMatthew G. Knepley 797171f0bbf9SMatthew G. Knepley PetscInt *idx; 797271f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 797371f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 79747773e69fSMatthew G. Knepley 797571f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 79767773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79777773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 797836fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 79794f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 79804f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 79814f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 79824f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 79839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 798463a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 79859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 798671f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 798707218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7988c459fbc1SJed Brown if (useClPerm) { 7989c459fbc1SJed Brown PetscInt depth, clsize; 79909566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7991c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7992c459fbc1SJed Brown PetscInt dof; 79939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7994c459fbc1SJed Brown clsize += dof; 7995c459fbc1SJed Brown } 79969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7997c459fbc1SJed Brown } 799871f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 799971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 80007773e69fSMatthew G. Knepley PetscInt dof, fdof; 80017773e69fSMatthew G. Knepley 80029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 80037773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 80049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 80057773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 80067773e69fSMatthew G. Knepley } 800771f0bbf9SMatthew G. Knepley Ni += dof; 80087773e69fSMatthew G. Knepley } 80097773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 80101dca8a05SBarry 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); 801171f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 801271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80139566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80149566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 801571f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 801671f0bbf9SMatthew G. Knepley if (values && flips[f]) { 801771f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 80186ecaa68aSToby Isaac 801971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 802071f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 802171f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 802271f0bbf9SMatthew G. Knepley 80239566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 80249566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 802571f0bbf9SMatthew G. Knepley if (flip) { 802671f0bbf9SMatthew G. Knepley PetscInt i, j, k; 802771f0bbf9SMatthew G. Knepley 802871f0bbf9SMatthew G. Knepley if (!valCopy) { 80299566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 803071f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 803171f0bbf9SMatthew G. Knepley *values = valCopy; 803271f0bbf9SMatthew G. Knepley } 803371f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 803471f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 803571f0bbf9SMatthew G. Knepley 803671f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 803771f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 803871f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 80396ecaa68aSToby Isaac } 80406ecaa68aSToby Isaac } 804171f0bbf9SMatthew G. Knepley } 804271f0bbf9SMatthew G. Knepley foffset += fdof; 804371f0bbf9SMatthew G. Knepley } 804471f0bbf9SMatthew G. Knepley } 804571f0bbf9SMatthew G. Knepley } 804671f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 80479566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 804871f0bbf9SMatthew G. Knepley if (NclC) { 80499566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 805071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80519566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80529566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 805371f0bbf9SMatthew G. Knepley } 805471f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80559566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 80569566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 805771f0bbf9SMatthew G. Knepley } 80589566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 805971f0bbf9SMatthew G. Knepley Ncl = NclC; 806071f0bbf9SMatthew G. Knepley Ni = NiC; 806171f0bbf9SMatthew G. Knepley points = pointsC; 806271f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 806371f0bbf9SMatthew G. Knepley } 806471f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 80659566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 806671f0bbf9SMatthew G. Knepley if (Nf) { 806771f0bbf9SMatthew G. Knepley PetscInt idxOff; 806871f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 806971f0bbf9SMatthew G. Knepley 80709371c9d4SSatish Balay if (outOffsets) { 80719371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 80729371c9d4SSatish Balay } 80739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 807471f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 807571f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 807671f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 807771f0bbf9SMatthew G. Knepley 80789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 80797773e69fSMatthew G. Knepley } 80807773e69fSMatthew G. Knepley } else { 808171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 808271f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 808371f0bbf9SMatthew G. Knepley 80849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 808571f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 808671f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 808771f0bbf9SMatthew G. Knepley * global section. */ 80889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 808971f0bbf9SMatthew G. Knepley } 809071f0bbf9SMatthew G. Knepley } 809171f0bbf9SMatthew G. Knepley } else { 809271f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 809371f0bbf9SMatthew G. Knepley 809471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 809571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 80964acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 80974acb8e1eSToby Isaac 80989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 809971f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 810071f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 81019566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 81027773e69fSMatthew G. Knepley } 81037773e69fSMatthew G. Knepley } 810471f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 810571f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 81069566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 81079566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 81084acb8e1eSToby Isaac } 810971f0bbf9SMatthew G. Knepley if (NclC) { 81109566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 81117773e69fSMatthew G. Knepley } else { 81129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 81137773e69fSMatthew G. Knepley } 811471f0bbf9SMatthew G. Knepley 811571f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 811671f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 81173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81187773e69fSMatthew G. Knepley } 81197773e69fSMatthew G. Knepley 81207cd05799SMatthew G. Knepley /*@C 812171f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 81227cd05799SMatthew G. Knepley 81237cd05799SMatthew G. Knepley Not collective 81247cd05799SMatthew G. Knepley 81257cd05799SMatthew G. Knepley Input Parameters: 8126a1cb98faSBarry Smith + dm - The `DM` 8127a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8128a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 812971f0bbf9SMatthew G. Knepley . point - The point defining the closure 813071f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 813171f0bbf9SMatthew G. Knepley 813271f0bbf9SMatthew G. Knepley Output Parameters: 813371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 813471f0bbf9SMatthew G. Knepley . indices - The dof indices 813520f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 813620f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 813771f0bbf9SMatthew G. Knepley 8138a1cb98faSBarry Smith Level: advanced 813971f0bbf9SMatthew G. Knepley 8140a1cb98faSBarry Smith Notes: 8141a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8142a1cb98faSBarry Smith 8143a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 814471f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 814571f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 814671f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 814771f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 81487cd05799SMatthew G. Knepley 81491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 81507cd05799SMatthew G. Knepley @*/ 8151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8152d71ae5a4SJacob Faibussowitsch { 81537773e69fSMatthew G. Knepley PetscFunctionBegin; 81547773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81554f572ea9SToby Isaac PetscAssertPointer(indices, 7); 81569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 81573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81587773e69fSMatthew G. Knepley } 81597773e69fSMatthew G. Knepley 8160e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8161d71ae5a4SJacob Faibussowitsch { 8162552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8163552f7358SJed Brown PetscInt *indices; 816471f0bbf9SMatthew G. Knepley PetscInt numIndices; 816571f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8166552f7358SJed Brown PetscErrorCode ierr; 8167552f7358SJed Brown 8168552f7358SJed Brown PetscFunctionBegin; 8169552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 81709566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 81713dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 81729566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 81733dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8174e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8175552f7358SJed Brown 8176e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81770d644c17SKarl Rupp 81789566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8179d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81804a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8181552f7358SJed Brown if (ierr) { 8182552f7358SJed Brown PetscMPIInt rank; 8183552f7358SJed Brown 81849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81859566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81869566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81889566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8189c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8190552f7358SJed Brown } 81914a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81924a1e0b3eSMatthew G. Knepley PetscInt i; 81939566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 819463a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81959566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81964a1e0b3eSMatthew G. Knepley } 819771f0bbf9SMatthew G. Knepley 81989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81999566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 82003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82014acb8e1eSToby Isaac } 820271f0bbf9SMatthew G. Knepley 82034a1e0b3eSMatthew G. Knepley /*@C 8204e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8205e8e188d2SZach Atkins 8206e8e188d2SZach Atkins Not collective 8207e8e188d2SZach Atkins 8208e8e188d2SZach Atkins Input Parameters: 8209e8e188d2SZach Atkins + dm - The `DM` 8210e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8211e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8212e8e188d2SZach Atkins . A - The matrix 8213e8e188d2SZach Atkins . point - The point in the `DM` 8214e8e188d2SZach Atkins . values - The array of values 8215e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8216e8e188d2SZach Atkins 8217e8e188d2SZach Atkins Level: intermediate 8218e8e188d2SZach Atkins 8219e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8220e8e188d2SZach Atkins @*/ 8221e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8222e8e188d2SZach Atkins { 8223e8e188d2SZach Atkins PetscFunctionBegin; 8224e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8225e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8226e8e188d2SZach Atkins } 8227e8e188d2SZach Atkins 8228e8e188d2SZach Atkins /*@C 822960225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 82304a1e0b3eSMatthew G. Knepley 82314a1e0b3eSMatthew G. Knepley Not collective 82324a1e0b3eSMatthew G. Knepley 82334a1e0b3eSMatthew G. Knepley Input Parameters: 8234a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 823520f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8236e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 823720f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8238a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 823920f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8240e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 824120f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 82424a1e0b3eSMatthew G. Knepley . A - The matrix 8243a1cb98faSBarry Smith . point - The point in the `DM` 82444a1e0b3eSMatthew G. Knepley . values - The array of values 8245a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 82464a1e0b3eSMatthew G. Knepley 82474a1e0b3eSMatthew G. Knepley Level: intermediate 82484a1e0b3eSMatthew G. Knepley 82491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 82504a1e0b3eSMatthew G. Knepley @*/ 8251e8e188d2SZach 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) 8252d71ae5a4SJacob Faibussowitsch { 825371f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 825471f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 825571f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 825671f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 825771f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 825871f0bbf9SMatthew G. Knepley 825971f0bbf9SMatthew G. Knepley PetscFunctionBegin; 826071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 82619566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 826271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 82639566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 826471f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8265e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 82669566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8267e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 82689566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8269e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8270e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 827171f0bbf9SMatthew G. Knepley 8272e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8273e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 827471f0bbf9SMatthew G. Knepley 82759566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 8276d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 82774a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 827871f0bbf9SMatthew G. Knepley if (ierr) { 827971f0bbf9SMatthew G. Knepley PetscMPIInt rank; 828071f0bbf9SMatthew G. Knepley 82819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82829566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82839566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 82859566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 82869566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 8287d3d1a6afSToby Isaac } 828871f0bbf9SMatthew G. Knepley 8289e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8290e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 82919566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 82923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8293552f7358SJed Brown } 8294552f7358SJed Brown 8295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8296d71ae5a4SJacob Faibussowitsch { 8297de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8298de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8299de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8300de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 830117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8302de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8303412e9a14SMatthew G. Knepley DMPolytopeType ct; 83044ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8305de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8306de41b84cSMatthew G. Knepley 8307de41b84cSMatthew G. Knepley PetscFunctionBegin; 8308de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8309de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83109566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8311de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 83129566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8313de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 83149566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8315de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 83169566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8317de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8318de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 83199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 832063a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 83219566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 83229566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8323de41b84cSMatthew G. Knepley /* Column indices */ 83249566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83254ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8326de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8327de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 83289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8329de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8330de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8331de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8332de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8333de41b84cSMatthew G. Knepley ++q; 8334de41b84cSMatthew G. Knepley } 8335de41b84cSMatthew G. Knepley } 8336de41b84cSMatthew G. Knepley numCPoints = q; 8337de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8338de41b84cSMatthew G. Knepley PetscInt fdof; 8339de41b84cSMatthew G. Knepley 83409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 83414ca5e9f5SMatthew G. Knepley if (!dof) continue; 8342de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8344de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8345de41b84cSMatthew G. Knepley } 8346de41b84cSMatthew G. Knepley numCIndices += dof; 8347de41b84cSMatthew G. Knepley } 8348de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8349de41b84cSMatthew G. Knepley /* Row indices */ 83509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8351412e9a14SMatthew G. Knepley { 8352012bc364SMatthew G. Knepley DMPlexTransform tr; 8353012bc364SMatthew G. Knepley DMPolytopeType *rct; 8354012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8355012bc364SMatthew G. Knepley 83569566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 83579566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 83589566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8359012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 83609566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8361412e9a14SMatthew G. Knepley } 83629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8363de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8364de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 83659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8366de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 83679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8368de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8369de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 83709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 83714ca5e9f5SMatthew G. Knepley if (!dof) continue; 83729371c9d4SSatish Balay for (s = 0; s < q; ++s) 83739371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 83744ca5e9f5SMatthew G. Knepley if (s < q) continue; 8375de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8376de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8377de41b84cSMatthew G. Knepley ++q; 8378de41b84cSMatthew G. Knepley } 8379de41b84cSMatthew G. Knepley } 83809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8381de41b84cSMatthew G. Knepley } 8382de41b84cSMatthew G. Knepley numFPoints = q; 8383de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8384de41b84cSMatthew G. Knepley PetscInt fdof; 8385de41b84cSMatthew G. Knepley 83869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83874ca5e9f5SMatthew G. Knepley if (!dof) continue; 8388de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8390de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8391de41b84cSMatthew G. Knepley } 8392de41b84cSMatthew G. Knepley numFIndices += dof; 8393de41b84cSMatthew G. Knepley } 8394de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8395de41b84cSMatthew G. Knepley 83961dca8a05SBarry 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); 83971dca8a05SBarry 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); 83989566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83999566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8400de41b84cSMatthew G. Knepley if (numFields) { 84014acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84024acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84034acb8e1eSToby Isaac 84044acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8407de41b84cSMatthew G. Knepley } 84084acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84109566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84114acb8e1eSToby Isaac } 84124acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84149566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84154acb8e1eSToby Isaac } 84164acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84179566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84189566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8419de41b84cSMatthew G. Knepley } 8420de41b84cSMatthew G. Knepley } else { 84214acb8e1eSToby Isaac const PetscInt **permsF = NULL; 84224acb8e1eSToby Isaac const PetscInt **permsC = NULL; 84234acb8e1eSToby Isaac 84249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84264acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 84274acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 84284acb8e1eSToby Isaac 84299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84309566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8431de41b84cSMatthew G. Knepley } 84324acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 84334acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 84344acb8e1eSToby Isaac 84359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8437de41b84cSMatthew G. Knepley } 84389566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8440de41b84cSMatthew G. Knepley } 84419566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84424acb8e1eSToby Isaac /* TODO: flips */ 8443d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8444de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8445de41b84cSMatthew G. Knepley if (ierr) { 8446de41b84cSMatthew G. Knepley PetscMPIInt rank; 8447de41b84cSMatthew G. Knepley 84489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 84499566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 84509566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 84519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84529566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8453de41b84cSMatthew G. Knepley } 84549566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 84559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84569566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84579566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 84583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8459de41b84cSMatthew G. Knepley } 8460de41b84cSMatthew G. Knepley 8461d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8462d71ae5a4SJacob Faibussowitsch { 84637c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 84647c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8465230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 846617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8467412e9a14SMatthew G. Knepley DMPolytopeType ct; 84687c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 84697c927364SMatthew G. Knepley 84707c927364SMatthew G. Knepley PetscFunctionBegin; 84717c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 84727c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 84739566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 84747c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84759566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84767c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84779566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84787c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84799566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84807c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 848263a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84837c927364SMatthew G. Knepley /* Column indices */ 84849566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84857c927364SMatthew G. Knepley maxFPoints = numCPoints; 84867c927364SMatthew G. Knepley /* Compress out points not in the section */ 84877c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84897c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84907c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84917c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84927c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84937c927364SMatthew G. Knepley ++q; 84947c927364SMatthew G. Knepley } 84957c927364SMatthew G. Knepley } 84967c927364SMatthew G. Knepley numCPoints = q; 84977c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84987c927364SMatthew G. Knepley PetscInt fdof; 84997c927364SMatthew G. Knepley 85009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 85017c927364SMatthew G. Knepley if (!dof) continue; 85027c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 85047c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 85057c927364SMatthew G. Knepley } 85067c927364SMatthew G. Knepley numCIndices += dof; 85077c927364SMatthew G. Knepley } 85087c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 85097c927364SMatthew G. Knepley /* Row indices */ 85109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8511412e9a14SMatthew G. Knepley { 8512012bc364SMatthew G. Knepley DMPlexTransform tr; 8513012bc364SMatthew G. Knepley DMPolytopeType *rct; 8514012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8515012bc364SMatthew G. Knepley 85169566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 85179566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 85189566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8519012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 85209566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8521412e9a14SMatthew G. Knepley } 85229566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 85237c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 85247c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 85259566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 85267c927364SMatthew G. Knepley /* Compress out points not in the section */ 85279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 85287c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 85297c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 85309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 85317c927364SMatthew G. Knepley if (!dof) continue; 85329371c9d4SSatish Balay for (s = 0; s < q; ++s) 85339371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 85347c927364SMatthew G. Knepley if (s < q) continue; 85357c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 85367c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 85377c927364SMatthew G. Knepley ++q; 85387c927364SMatthew G. Knepley } 85397c927364SMatthew G. Knepley } 85409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 85417c927364SMatthew G. Knepley } 85427c927364SMatthew G. Knepley numFPoints = q; 85437c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 85447c927364SMatthew G. Knepley PetscInt fdof; 85457c927364SMatthew G. Knepley 85469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 85477c927364SMatthew G. Knepley if (!dof) continue; 85487c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 85507c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 85517c927364SMatthew G. Knepley } 85527c927364SMatthew G. Knepley numFIndices += dof; 85537c927364SMatthew G. Knepley } 85547c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 85557c927364SMatthew G. Knepley 85561dca8a05SBarry 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); 85571dca8a05SBarry 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); 85587c927364SMatthew G. Knepley if (numFields) { 85594acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 85604acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 85614acb8e1eSToby Isaac 85624acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85657c927364SMatthew G. Knepley } 85664acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 85679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85689566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 85694acb8e1eSToby Isaac } 85704acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 85719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85729566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 85734acb8e1eSToby Isaac } 85744acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85759566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85769566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85777c927364SMatthew G. Knepley } 85787c927364SMatthew G. Knepley } else { 85794acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85804acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85814acb8e1eSToby Isaac 85829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85844acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85854acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85864acb8e1eSToby Isaac 85879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85889566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85897c927364SMatthew G. Knepley } 85904acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85914acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85924acb8e1eSToby Isaac 85939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85949566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85957c927364SMatthew G. Knepley } 85969566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85979566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85987c927364SMatthew G. Knepley } 85999566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 86009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 86013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86027c927364SMatthew G. Knepley } 86037c927364SMatthew G. Knepley 86047cd05799SMatthew G. Knepley /*@C 86057cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 86067cd05799SMatthew G. Knepley 86077cd05799SMatthew G. Knepley Input Parameter: 8608a1cb98faSBarry Smith . dm - The `DMPLEX` object 86097cd05799SMatthew G. Knepley 86107cd05799SMatthew G. Knepley Output Parameter: 86117cd05799SMatthew G. Knepley . cellHeight - The height of a cell 86127cd05799SMatthew G. Knepley 86137cd05799SMatthew G. Knepley Level: developer 86147cd05799SMatthew G. Knepley 86151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 86167cd05799SMatthew G. Knepley @*/ 8617d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8618d71ae5a4SJacob Faibussowitsch { 8619552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8620552f7358SJed Brown 8621552f7358SJed Brown PetscFunctionBegin; 8622552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86234f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8624552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 86253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8626552f7358SJed Brown } 8627552f7358SJed Brown 86287cd05799SMatthew G. Knepley /*@C 86297cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 86307cd05799SMatthew G. Knepley 86317cd05799SMatthew G. Knepley Input Parameters: 8632a1cb98faSBarry Smith + dm - The `DMPLEX` object 86337cd05799SMatthew G. Knepley - cellHeight - The height of a cell 86347cd05799SMatthew G. Knepley 86357cd05799SMatthew G. Knepley Level: developer 86367cd05799SMatthew G. Knepley 86371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 86387cd05799SMatthew G. Knepley @*/ 8639d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8640d71ae5a4SJacob Faibussowitsch { 8641552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8642552f7358SJed Brown 8643552f7358SJed Brown PetscFunctionBegin; 8644552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8645552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 86463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8647552f7358SJed Brown } 8648552f7358SJed Brown 8649e6139122SMatthew G. Knepley /*@ 86502827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8651e6139122SMatthew G. Knepley 86522827ebadSStefano Zampini Input Parameters: 86532827ebadSStefano Zampini + dm - The `DMPLEX` object 86542827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8655e6139122SMatthew G. Knepley 8656e6139122SMatthew G. Knepley Output Parameters: 86572827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 86582827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8659e6139122SMatthew G. Knepley 86602a9f31c0SMatthew G. Knepley Level: advanced 8661e6139122SMatthew G. Knepley 86622827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8663e6139122SMatthew G. Knepley @*/ 86642827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8665d71ae5a4SJacob Faibussowitsch { 86662827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 86672827ebadSStefano Zampini DMLabel label; 86682827ebadSStefano Zampini PetscInt pStart, pEnd; 8669e6139122SMatthew G. Knepley 8670e6139122SMatthew G. Knepley PetscFunctionBegin; 8671e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86722827ebadSStefano Zampini if (start) { 86734f572ea9SToby Isaac PetscAssertPointer(start, 3); 86742827ebadSStefano Zampini *start = 0; 86752827ebadSStefano Zampini } 86762827ebadSStefano Zampini if (end) { 86774f572ea9SToby Isaac PetscAssertPointer(end, 4); 86782827ebadSStefano Zampini *end = 0; 86792827ebadSStefano Zampini } 86802827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86812827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86822827ebadSStefano Zampini if (mesh->tr) { 86832827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86842827ebadSStefano Zampini } else { 86852827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86862827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86872827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86882827ebadSStefano Zampini } 86893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8690e6139122SMatthew G. Knepley } 8691e6139122SMatthew G. Knepley 8692d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8693d71ae5a4SJacob Faibussowitsch { 8694552f7358SJed Brown PetscSection section, globalSection; 8695552f7358SJed Brown PetscInt *numbers, p; 8696552f7358SJed Brown 8697552f7358SJed Brown PetscFunctionBegin; 8698d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 86999566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 87009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 870148a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 87029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8703eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 87049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8705552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 87069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8707ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8708ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8709552f7358SJed Brown } 87109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8711ef48cebcSMatthew G. Knepley if (globalSize) { 8712ef48cebcSMatthew G. Knepley PetscLayout layout; 87139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 87149566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 87159566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8716ef48cebcSMatthew G. Knepley } 87179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 87189566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 87193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8720552f7358SJed Brown } 8721552f7358SJed Brown 8722d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8723d71ae5a4SJacob Faibussowitsch { 8724412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8725552f7358SJed Brown 8726552f7358SJed Brown PetscFunctionBegin; 87279566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 87289566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 87299566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 87309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 87313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8732552f7358SJed Brown } 873381ed3555SMatthew G. Knepley 87348dab3259SMatthew G. Knepley /*@ 87357cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 87367cd05799SMatthew G. Knepley 87377cd05799SMatthew G. Knepley Input Parameter: 8738a1cb98faSBarry Smith . dm - The `DMPLEX` object 87397cd05799SMatthew G. Knepley 87407cd05799SMatthew G. Knepley Output Parameter: 87417cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 87427cd05799SMatthew G. Knepley 87437cd05799SMatthew G. Knepley Level: developer 87447cd05799SMatthew G. Knepley 87451cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 87467cd05799SMatthew G. Knepley @*/ 8747d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8748d71ae5a4SJacob Faibussowitsch { 874981ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 875081ed3555SMatthew G. Knepley 875181ed3555SMatthew G. Knepley PetscFunctionBegin; 875281ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87539566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8754552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 87553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8756552f7358SJed Brown } 8757552f7358SJed Brown 8758d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8759d71ae5a4SJacob Faibussowitsch { 8760412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 876181ed3555SMatthew G. Knepley 876281ed3555SMatthew G. Knepley PetscFunctionBegin; 876381ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 87659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 87663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 876781ed3555SMatthew G. Knepley } 876881ed3555SMatthew G. Knepley 87698dab3259SMatthew G. Knepley /*@ 87706aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 87717cd05799SMatthew G. Knepley 87727cd05799SMatthew G. Knepley Input Parameter: 8773a1cb98faSBarry Smith . dm - The `DMPLEX` object 87747cd05799SMatthew G. Knepley 87757cd05799SMatthew G. Knepley Output Parameter: 87767cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87777cd05799SMatthew G. Knepley 87787cd05799SMatthew G. Knepley Level: developer 87797cd05799SMatthew G. Knepley 87801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87817cd05799SMatthew G. Knepley @*/ 8782d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8783d71ae5a4SJacob Faibussowitsch { 8784552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8785552f7358SJed Brown 8786552f7358SJed Brown PetscFunctionBegin; 8787552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87889566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8789552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8791552f7358SJed Brown } 8792552f7358SJed Brown 87938dab3259SMatthew G. Knepley /*@ 8794966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8795966484cfSJed Brown 879620f4b53cSBarry Smith Collective 87977cd05799SMatthew G. Knepley 87987cd05799SMatthew G. Knepley Input Parameter: 8799a1cb98faSBarry Smith . dm - The `DMPLEX` object 88007cd05799SMatthew G. Knepley 88017cd05799SMatthew G. Knepley Output Parameter: 88027cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 88037cd05799SMatthew G. Knepley 8804a1cb98faSBarry Smith Level: developer 8805966484cfSJed Brown 8806a1cb98faSBarry Smith Notes: 8807a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8808966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8809966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8810966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8811966484cfSJed Brown 8812966484cfSJed Brown The partitioned mesh is 8813966484cfSJed Brown ``` 8814966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8815966484cfSJed Brown ``` 8816966484cfSJed Brown and its global numbering is 8817966484cfSJed Brown ``` 8818966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8819966484cfSJed Brown ``` 8820966484cfSJed Brown Then the global numbering is provided as 8821966484cfSJed Brown ``` 8822966484cfSJed Brown [0] Number of indices in set 5 8823966484cfSJed Brown [0] 0 0 8824966484cfSJed Brown [0] 1 1 8825966484cfSJed Brown [0] 2 3 8826966484cfSJed Brown [0] 3 4 8827966484cfSJed Brown [0] 4 -6 8828966484cfSJed Brown [1] Number of indices in set 3 8829966484cfSJed Brown [1] 0 2 8830966484cfSJed Brown [1] 1 5 8831966484cfSJed Brown [1] 2 6 8832966484cfSJed Brown ``` 8833966484cfSJed Brown 88341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 88357cd05799SMatthew G. Knepley @*/ 8836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8837d71ae5a4SJacob Faibussowitsch { 8838ef48cebcSMatthew G. Knepley IS nums[4]; 8839862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8840ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 88410c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8842ef48cebcSMatthew G. Knepley 8843ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8844ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 88460c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 88479566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 88480c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8849862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8850862913ffSStefano Zampini PetscInt end; 8851862913ffSStefano Zampini 8852862913ffSStefano Zampini depths[d] = depth - d; 88539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 88540c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8855862913ffSStefano Zampini } 88560c15888dSMatthew G. Knepley if (empty) 88570c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 88580c15888dSMatthew G. Knepley depths[d] = -1; 88590c15888dSMatthew G. Knepley starts[d] = -1; 88600c15888dSMatthew G. Knepley } 88610c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 88621c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8863ad540459SPierre 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]); 88640c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8865ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8866ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8867ef48cebcSMatthew G. Knepley 88689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 88699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8870ef48cebcSMatthew G. Knepley shift += gsize; 8871ef48cebcSMatthew G. Knepley } 8872d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 88739566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8875ef48cebcSMatthew G. Knepley } 8876ef48cebcSMatthew G. Knepley 887708a22f4bSMatthew G. Knepley /*@ 887808a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 887908a22f4bSMatthew G. Knepley 888008a22f4bSMatthew G. Knepley Input Parameter: 8881a1cb98faSBarry Smith . dm - The `DMPLEX` object 888208a22f4bSMatthew G. Knepley 888308a22f4bSMatthew G. Knepley Output Parameter: 888408a22f4bSMatthew G. Knepley . ranks - The rank field 888508a22f4bSMatthew G. Knepley 8886a1cb98faSBarry Smith Options Database Key: 888720f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 888808a22f4bSMatthew G. Knepley 888908a22f4bSMatthew G. Knepley Level: intermediate 889008a22f4bSMatthew G. Knepley 88911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 889208a22f4bSMatthew G. Knepley @*/ 8893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8894d71ae5a4SJacob Faibussowitsch { 889508a22f4bSMatthew G. Knepley DM rdm; 889608a22f4bSMatthew G. Knepley PetscFE fe; 889708a22f4bSMatthew G. Knepley PetscScalar *r; 889808a22f4bSMatthew G. Knepley PetscMPIInt rank; 8899a55f9a55SMatthew G. Knepley DMPolytopeType ct; 890008a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8901a55f9a55SMatthew G. Knepley PetscBool simplex; 890208a22f4bSMatthew G. Knepley 890308a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8904f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89054f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 89069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 89079566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 89089566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 89099566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 89109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8911a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 89129566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 89139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 89149566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89159566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89169566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89179566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 89189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 89199566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 892008a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 892108a22f4bSMatthew G. Knepley PetscScalar *lr; 892208a22f4bSMatthew G. Knepley 89239566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 892471f09efeSPierre Jolivet if (lr) *lr = rank; 892508a22f4bSMatthew G. Knepley } 89269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 89279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 892908a22f4bSMatthew G. Knepley } 893008a22f4bSMatthew G. Knepley 8931ca8062c8SMatthew G. Knepley /*@ 8932acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 893318e14f0cSMatthew G. Knepley 893418e14f0cSMatthew G. Knepley Input Parameters: 893520f4b53cSBarry Smith + dm - The `DMPLEX` 893620f4b53cSBarry Smith - label - The `DMLabel` 893718e14f0cSMatthew G. Knepley 893818e14f0cSMatthew G. Knepley Output Parameter: 893918e14f0cSMatthew G. Knepley . val - The label value field 894018e14f0cSMatthew G. Knepley 894120f4b53cSBarry Smith Options Database Key: 894220f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 894318e14f0cSMatthew G. Knepley 894418e14f0cSMatthew G. Knepley Level: intermediate 894518e14f0cSMatthew G. Knepley 89461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 894718e14f0cSMatthew G. Knepley @*/ 8948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8949d71ae5a4SJacob Faibussowitsch { 89501033741fSStefano Zampini DM rdm, plex; 8951acf3173eSStefano Zampini Vec lval; 8952acf3173eSStefano Zampini PetscSection section; 895318e14f0cSMatthew G. Knepley PetscFE fe; 895418e14f0cSMatthew G. Knepley PetscScalar *v; 8955acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 8956acf3173eSStefano Zampini DMPolytopeType ct; 8957acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 8958acf3173eSStefano Zampini const char *lname, *prefix; 895918e14f0cSMatthew G. Knepley 896018e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 896118e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89624f572ea9SToby Isaac PetscAssertPointer(label, 2); 89634f572ea9SToby Isaac PetscAssertPointer(val, 3); 89649566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 8965acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 8966acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 8967acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 8968acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 89699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 8970acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 8971acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 8972acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 8973acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 8974acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 89759566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 89769566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 89779566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 89789566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 8979acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 8980acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 8981acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 8982acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 8983acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 8984acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 8985acf3173eSStefano Zampini PetscInt cval, dof, off; 898618e14f0cSMatthew G. Knepley 8987acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 8988acf3173eSStefano Zampini if (!dof) continue; 8989acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 8990acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 8991acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 899218e14f0cSMatthew G. Knepley } 8993acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 8994acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 8995acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 89969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 899818e14f0cSMatthew G. Knepley } 899918e14f0cSMatthew G. Knepley 900018e14f0cSMatthew G. Knepley /*@ 9001ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 9002ca8062c8SMatthew G. Knepley 900369916449SMatthew G. Knepley Input Parameter: 9004a1cb98faSBarry Smith . dm - The `DMPLEX` object 9005a1cb98faSBarry Smith 9006a1cb98faSBarry Smith Level: developer 9007ca8062c8SMatthew G. Knepley 900895eb5ee5SVaclav Hapla Notes: 900995eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 901095eb5ee5SVaclav Hapla 901120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9012ca8062c8SMatthew G. Knepley 90131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9014ca8062c8SMatthew G. Knepley @*/ 9015d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 9016d71ae5a4SJacob Faibussowitsch { 9017ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 9018ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 9019ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 902057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 902157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9022ca8062c8SMatthew G. Knepley 9023ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9024ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90259566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 90269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 90279566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9028ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 90299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9030ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 90319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 90329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9033ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 903442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 903542e66dfaSMatthew G. Knepley PetscInt d; 903642e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 90379371c9d4SSatish Balay if (cone[c] == cone[d]) { 90389371c9d4SSatish Balay dup = PETSC_TRUE; 90399371c9d4SSatish Balay break; 90409371c9d4SSatish Balay } 904142e66dfaSMatthew G. Knepley } 90429566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 90439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9044ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9045ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9046ca8062c8SMatthew G. Knepley } 904742e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 904863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 904948a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 90509566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 905163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 905248a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 90539566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 905463a3b9bcSJacob 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]); 9055f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9056ca8062c8SMatthew G. Knepley } 905742e66dfaSMatthew G. Knepley } 90589566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 90599371c9d4SSatish Balay if (p != pp) { 90609371c9d4SSatish Balay storagecheck = PETSC_FALSE; 90619371c9d4SSatish Balay continue; 90629371c9d4SSatish Balay } 90639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 90649566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9065ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 90669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 90679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9068ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 90699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 90709371c9d4SSatish Balay if (cone[c] != pp) { 90719371c9d4SSatish Balay c = 0; 90729371c9d4SSatish Balay break; 90739371c9d4SSatish Balay } 9074ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9075ca8062c8SMatthew G. Knepley } 9076ca8062c8SMatthew G. Knepley if (c >= coneSize) { 907763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 907848a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 90799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 908063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 908148a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 90829566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 908363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9084ca8062c8SMatthew G. Knepley } 9085ca8062c8SMatthew G. Knepley } 9086ca8062c8SMatthew G. Knepley } 908757beb4faSStefano Zampini if (storagecheck) { 90889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 90899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 909063a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 909157beb4faSStefano Zampini } 90923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9093ca8062c8SMatthew G. Knepley } 9094ca8062c8SMatthew G. Knepley 9095412e9a14SMatthew G. Knepley /* 9096412e9a14SMatthew 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. 9097412e9a14SMatthew G. Knepley */ 9098d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9099d71ae5a4SJacob Faibussowitsch { 9100412e9a14SMatthew G. Knepley DMPolytopeType cct; 9101412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9102412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9103412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9104412e9a14SMatthew G. Knepley 9105412e9a14SMatthew G. Knepley PetscFunctionBegin; 9106412e9a14SMatthew G. Knepley *unsplit = 0; 9107412e9a14SMatthew G. Knepley switch (ct) { 9108d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9109d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9110d71ae5a4SJacob Faibussowitsch break; 9111412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 91129566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91139566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9114412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 91159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9116412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9117412e9a14SMatthew G. Knepley } 9118412e9a14SMatthew G. Knepley break; 9119412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9120412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 91219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9123412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 91249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 91259566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9126412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 91279566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9128412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9129412e9a14SMatthew G. Knepley PetscInt p; 91309371c9d4SSatish Balay for (p = 0; p < npt; ++p) 91319371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9132412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9133412e9a14SMatthew G. Knepley } 9134412e9a14SMatthew G. Knepley } 9135412e9a14SMatthew G. Knepley } 9136412e9a14SMatthew G. Knepley break; 9137d71ae5a4SJacob Faibussowitsch default: 9138d71ae5a4SJacob Faibussowitsch break; 9139412e9a14SMatthew G. Knepley } 9140412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 91419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9142412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9143412e9a14SMatthew G. Knepley } 91443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9145412e9a14SMatthew G. Knepley } 9146412e9a14SMatthew G. Knepley 9147ca8062c8SMatthew G. Knepley /*@ 9148ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9149ca8062c8SMatthew G. Knepley 9150ca8062c8SMatthew G. Knepley Input Parameters: 9151a1cb98faSBarry Smith + dm - The `DMPLEX` object 915258723a97SMatthew G. Knepley - cellHeight - Normally 0 9153ca8062c8SMatthew G. Knepley 9154a1cb98faSBarry Smith Level: developer 9155a1cb98faSBarry Smith 915695eb5ee5SVaclav Hapla Notes: 915795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 915825c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9159ca8062c8SMatthew G. Knepley 916020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 916195eb5ee5SVaclav Hapla 91621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9163ca8062c8SMatthew G. Knepley @*/ 9164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9165d71ae5a4SJacob Faibussowitsch { 9166412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9167412e9a14SMatthew G. Knepley DMPolytopeType ct; 9168412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9169ca8062c8SMatthew G. Knepley 9170ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9171ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91729566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 91739566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 91749566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9175412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9176412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9177412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 917858723a97SMatthew G. Knepley 91799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 918063a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9181412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9182412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 91839566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 918463a3b9bcSJacob 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)); 9185412e9a14SMatthew G. Knepley } 91869566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 918758723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 918858723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9189412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 919058723a97SMatthew G. Knepley } 91919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9192412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9193412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9194412e9a14SMatthew G. Knepley PetscInt unsplit; 919542363296SMatthew G. Knepley 91969566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9197412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 919842363296SMatthew G. Knepley } 919963a3b9bcSJacob 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)); 920042363296SMatthew G. Knepley } 92013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9202ca8062c8SMatthew G. Knepley } 92039bf0dad6SMatthew G. Knepley 92049bf0dad6SMatthew G. Knepley /*@ 92059bf0dad6SMatthew 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 92069bf0dad6SMatthew G. Knepley 920720f4b53cSBarry Smith Collective 9208899ea2b8SJacob Faibussowitsch 92099bf0dad6SMatthew G. Knepley Input Parameters: 9210a1cb98faSBarry Smith + dm - The `DMPLEX` object 92119bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 92129bf0dad6SMatthew G. Knepley 9213a1cb98faSBarry Smith Level: developer 9214a1cb98faSBarry Smith 921545da879fSVaclav Hapla Notes: 921645da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 921745da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 921845da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 921945da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 92209bf0dad6SMatthew G. Knepley 9221a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 922295eb5ee5SVaclav Hapla 92231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 92249bf0dad6SMatthew G. Knepley @*/ 9225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9226d71ae5a4SJacob Faibussowitsch { 9227ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9228899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 92299bf0dad6SMatthew G. Knepley 92309bf0dad6SMatthew G. Knepley PetscFunctionBegin; 92319bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92328f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 92333ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 92348f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 92353ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 92363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9237899ea2b8SJacob Faibussowitsch } 9238899ea2b8SJacob Faibussowitsch 92399566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 92419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9242ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 92439566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 92443554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9245412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9246412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9247ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9248412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9249412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 92509bf0dad6SMatthew G. Knepley 92519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 92529566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9253412e9a14SMatthew G. Knepley if (unsplit) continue; 92549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 92559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 92569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 92579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92589bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 92599bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 92609bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 92619bf0dad6SMatthew G. Knepley } 92629566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 926363a3b9bcSJacob 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); 92649bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9265d4961f80SStefano Zampini DMPolytopeType fct; 92669bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 92679bf0dad6SMatthew G. Knepley 92689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 92699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 92709bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 92719bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 92729bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 92739bf0dad6SMatthew G. Knepley } 927463a3b9bcSJacob 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]); 92759bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9276b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9277b5a892a1SMatthew G. Knepley PetscInt v1; 9278b5a892a1SMatthew G. Knepley 92799566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 928063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 92819566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 928263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 92839566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 928463a3b9bcSJacob 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]); 9285b5a892a1SMatthew G. Knepley } 92869bf0dad6SMatthew G. Knepley } 92879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9288412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 92899bf0dad6SMatthew G. Knepley } 92909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92919566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92929bf0dad6SMatthew G. Knepley } 92933554e41dSMatthew G. Knepley } 92943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9295552f7358SJed Brown } 92963913d7c8SMatthew G. Knepley 9297bb6a34a8SMatthew G. Knepley /*@ 9298bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9299bb6a34a8SMatthew G. Knepley 9300bb6a34a8SMatthew G. Knepley Input Parameter: 9301a1cb98faSBarry Smith . dm - The `DMPLEX` object 9302a1cb98faSBarry Smith 9303a1cb98faSBarry Smith Level: developer 9304bb6a34a8SMatthew G. Knepley 930595eb5ee5SVaclav Hapla Notes: 930695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 930795eb5ee5SVaclav Hapla 930820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9309bb6a34a8SMatthew G. Knepley 93101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9311bb6a34a8SMatthew G. Knepley @*/ 9312d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9313d71ae5a4SJacob Faibussowitsch { 9314a2a9e04cSMatthew G. Knepley Vec coordinates; 9315bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9316bb6a34a8SMatthew G. Knepley PetscReal vol; 931751a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9318bb6a34a8SMatthew G. Knepley 9319bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 93209566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 93219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 93223ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 93239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9324bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 93259566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9326a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 93279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 93283ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9329412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9330412e9a14SMatthew G. Knepley DMPolytopeType ct; 9331412e9a14SMatthew G. Knepley PetscInt unsplit; 9332412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9333412e9a14SMatthew G. Knepley 93349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9335412e9a14SMatthew G. Knepley switch (ct) { 9336412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9337412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9338d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9339d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9340d71ae5a4SJacob Faibussowitsch break; 9341d71ae5a4SJacob Faibussowitsch default: 9342d71ae5a4SJacob Faibussowitsch break; 9343412e9a14SMatthew G. Knepley } 9344412e9a14SMatthew G. Knepley switch (ct) { 9345412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9346412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9347412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9348d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9349d71ae5a4SJacob Faibussowitsch continue; 9350d71ae5a4SJacob Faibussowitsch default: 9351d71ae5a4SJacob Faibussowitsch break; 9352412e9a14SMatthew G. Knepley } 93539566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9354412e9a14SMatthew G. Knepley if (unsplit) continue; 93559566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 93561dca8a05SBarry 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); 935763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 93586858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 93596858538eSMatthew G. Knepley if (depth > 1) { 93609566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 93611dca8a05SBarry 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); 936263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9363bb6a34a8SMatthew G. Knepley } 9364bb6a34a8SMatthew G. Knepley } 93653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9366bb6a34a8SMatthew G. Knepley } 9367bb6a34a8SMatthew G. Knepley 936803da9461SVaclav Hapla /*@ 936920f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 93707726db96SVaclav Hapla 937120f4b53cSBarry Smith Collective 937203da9461SVaclav Hapla 937303da9461SVaclav Hapla Input Parameters: 9374a1cb98faSBarry Smith + dm - The `DMPLEX` object 937520f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9376a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9377a1cb98faSBarry Smith 9378a1cb98faSBarry Smith Level: developer 937903da9461SVaclav Hapla 9380e83a0d2dSVaclav Hapla Notes: 9381e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 938203da9461SVaclav Hapla 9383a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 938495eb5ee5SVaclav Hapla 9385baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9386d7d32a9aSMatthew G. Knepley 93871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 938803da9461SVaclav Hapla @*/ 9389d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9390d71ae5a4SJacob Faibussowitsch { 93917726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93927726db96SVaclav Hapla const PetscInt *locals; 93937726db96SVaclav Hapla const PetscSFNode *remotes; 9394f0cfc026SVaclav Hapla PetscBool distributed; 93957726db96SVaclav Hapla MPI_Comm comm; 93967726db96SVaclav Hapla PetscMPIInt rank; 939703da9461SVaclav Hapla 939803da9461SVaclav Hapla PetscFunctionBegin; 939903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 94007726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 94017726db96SVaclav Hapla else pointSF = dm->sf; 94027726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 94037726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 94047726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94057726db96SVaclav Hapla { 94067726db96SVaclav Hapla PetscMPIInt mpiFlag; 94077726db96SVaclav Hapla 94087726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 94097726db96SVaclav 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); 94107726db96SVaclav Hapla } 94117726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 94129566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 94137726db96SVaclav Hapla if (!distributed) { 94147726db96SVaclav 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); 94153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 94168918e3e2SVaclav Hapla } 94177726db96SVaclav 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); 94187726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 941903da9461SVaclav Hapla 94207726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 94217726db96SVaclav Hapla { 94227726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 94237726db96SVaclav Hapla 94247726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 94257726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9426d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 94277726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 94287726db96SVaclav Hapla } 94297726db96SVaclav Hapla 94307726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 94317726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 94327726db96SVaclav 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); 94337726db96SVaclav Hapla } 94347726db96SVaclav Hapla 94357726db96SVaclav Hapla /* Check there are no cells in interface */ 94367726db96SVaclav Hapla if (!overlap) { 94377726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 94387726db96SVaclav Hapla 94399566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94409566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9441f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94427726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9443f5869d18SMatthew G. Knepley 94447726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 94457726db96SVaclav Hapla } 944603da9461SVaclav Hapla } 9447ece87651SVaclav Hapla 94487726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 94497726db96SVaclav Hapla { 94507726db96SVaclav Hapla const PetscInt *rootdegree; 94517726db96SVaclav Hapla 94527726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 94537726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9454f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 94557726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9456f5869d18SMatthew G. Knepley const PetscInt *cone; 9457f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9458f5869d18SMatthew G. Knepley 94599566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 94609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9461f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9462f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 94637726db96SVaclav Hapla if (locals) { 94649566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 94657726db96SVaclav Hapla } else { 94667726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 94677726db96SVaclav Hapla } 946863a3b9bcSJacob 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]); 9469f5869d18SMatthew G. Knepley } 9470f5869d18SMatthew G. Knepley } 9471ece87651SVaclav Hapla } 94727726db96SVaclav Hapla } 94733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 947403da9461SVaclav Hapla } 947503da9461SVaclav Hapla 94767f9d8d6cSVaclav Hapla /*@ 947720f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 94787f9d8d6cSVaclav Hapla 94797f9d8d6cSVaclav Hapla Input Parameter: 9480a1cb98faSBarry Smith . dm - The `DMPLEX` object 9481a1cb98faSBarry Smith 9482a1cb98faSBarry Smith Level: developer 94837f9d8d6cSVaclav Hapla 94847f9d8d6cSVaclav Hapla Notes: 94857f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 94867f9d8d6cSVaclav Hapla 948720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 94887f9d8d6cSVaclav Hapla 948920f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94907f9d8d6cSVaclav Hapla 94911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94927f9d8d6cSVaclav Hapla @*/ 9493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9494d71ae5a4SJacob Faibussowitsch { 94957f9d8d6cSVaclav Hapla PetscInt cellHeight; 94967f9d8d6cSVaclav Hapla 9497b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94987f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94999566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 95009566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 95019566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 95029566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9503d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 95049566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 95053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9506b5a892a1SMatthew G. Knepley } 9507b5a892a1SMatthew G. Knepley 95089371c9d4SSatish Balay typedef struct cell_stats { 9509068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9510068a5610SStefano Zampini PetscInt count; 9511068a5610SStefano Zampini } cell_stats_t; 9512068a5610SStefano Zampini 9513d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9514d71ae5a4SJacob Faibussowitsch { 9515068a5610SStefano Zampini PetscInt i, N = *len; 9516068a5610SStefano Zampini 9517068a5610SStefano Zampini for (i = 0; i < N; i++) { 9518068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9519068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9520068a5610SStefano Zampini 9521068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9522068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9523068a5610SStefano Zampini B->sum += A->sum; 9524068a5610SStefano Zampini B->squaresum += A->squaresum; 9525068a5610SStefano Zampini B->count += A->count; 9526068a5610SStefano Zampini } 9527068a5610SStefano Zampini } 9528068a5610SStefano Zampini 9529068a5610SStefano Zampini /*@ 953043fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9531068a5610SStefano Zampini 953220f4b53cSBarry Smith Collective 95338261a58bSMatthew G. Knepley 9534068a5610SStefano Zampini Input Parameters: 9535a1cb98faSBarry Smith + dm - The `DMPLEX` object 953620f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9537a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9538a1cb98faSBarry Smith 9539a1cb98faSBarry Smith Level: developer 9540068a5610SStefano Zampini 954195eb5ee5SVaclav Hapla Notes: 954295eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 954395eb5ee5SVaclav Hapla 9544a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9545068a5610SStefano Zampini 95461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9547068a5610SStefano Zampini @*/ 9548d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9549d71ae5a4SJacob Faibussowitsch { 9550068a5610SStefano Zampini DM dmCoarse; 955143fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 955243fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 955343fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 955443fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9555412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 955643fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9557068a5610SStefano Zampini 9558068a5610SStefano Zampini PetscFunctionBegin; 9559068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9560068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9561068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9562068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9563068a5610SStefano Zampini stats.count = 0; 9564068a5610SStefano Zampini 95659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 95669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 95679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 95689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 95699566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 95709566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9571412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9572068a5610SStefano Zampini PetscInt i; 9573068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9574068a5610SStefano Zampini 95759566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 957663a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 957743fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9578068a5610SStefano Zampini frobJ += J[i] * J[i]; 9579068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9580068a5610SStefano Zampini } 9581068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9582068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9583068a5610SStefano Zampini 9584068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9585068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9586068a5610SStefano Zampini stats.sum += cond; 9587068a5610SStefano Zampini stats.squaresum += cond2; 9588068a5610SStefano Zampini stats.count++; 95898261a58bSMatthew G. Knepley if (output && cond > limit) { 959043fa8764SMatthew G. Knepley PetscSection coordSection; 959143fa8764SMatthew G. Knepley Vec coordsLocal; 959243fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 959343fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 959443fa8764SMatthew G. Knepley 95959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95979566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 959863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 959943fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 960063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 960143fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 96029566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 96039566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 960443fa8764SMatthew G. Knepley } 96059566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 960643fa8764SMatthew G. Knepley } 96079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 960843fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 960943fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 961043fa8764SMatthew G. Knepley 961143fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 961243fa8764SMatthew G. Knepley PetscReal len; 961343fa8764SMatthew G. Knepley 96149566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 961563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 961643fa8764SMatthew G. Knepley } 961743fa8764SMatthew G. Knepley } 96189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 96199566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 962043fa8764SMatthew G. Knepley } 9621068a5610SStefano Zampini } 96229566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9623068a5610SStefano Zampini 9624068a5610SStefano Zampini if (size > 1) { 9625068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9626068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9627068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9628068a5610SStefano Zampini MPI_Op statReduce; 9629068a5610SStefano Zampini 96309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 96319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 96329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 96339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 96349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 96359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9636068a5610SStefano Zampini } else { 96379566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9638068a5610SStefano Zampini } 9639dd400576SPatrick Sanan if (rank == 0) { 9640068a5610SStefano Zampini count = globalStats.count; 9641068a5610SStefano Zampini min = globalStats.min; 9642068a5610SStefano Zampini max = globalStats.max; 9643068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9644068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9645068a5610SStefano Zampini } 9646068a5610SStefano Zampini 964748a46eb9SPierre 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)); 96489566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9649068a5610SStefano Zampini 96509566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9651068a5610SStefano Zampini if (dmCoarse) { 9652068a5610SStefano Zampini PetscBool isplex; 9653068a5610SStefano Zampini 96549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 96551baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9656068a5610SStefano Zampini } 96573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9658068a5610SStefano Zampini } 9659068a5610SStefano Zampini 9660f108dbd7SJacob Faibussowitsch /*@ 9661f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9662f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9663f108dbd7SJacob Faibussowitsch 966420f4b53cSBarry Smith Collective 9665f108dbd7SJacob Faibussowitsch 9666f108dbd7SJacob Faibussowitsch Input Parameters: 9667a1cb98faSBarry Smith + dm - The `DMPLEX` object 9668a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9669f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9670f108dbd7SJacob Faibussowitsch 9671f108dbd7SJacob Faibussowitsch Output Parameters: 967220f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9673a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9674f108dbd7SJacob Faibussowitsch 9675f108dbd7SJacob Faibussowitsch Options Database Keys: 9676a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9677f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9678f108dbd7SJacob Faibussowitsch 9679a1cb98faSBarry Smith Level: intermediate 9680a1cb98faSBarry Smith 9681f108dbd7SJacob Faibussowitsch Notes: 9682a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9683f108dbd7SJacob Faibussowitsch 9684a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9685f108dbd7SJacob Faibussowitsch 9686f108dbd7SJacob 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 9687f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9688f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9689f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9690f108dbd7SJacob Faibussowitsch 9691f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9692f108dbd7SJacob Faibussowitsch 9693a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9694f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9695f108dbd7SJacob Faibussowitsch 9696f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9697f108dbd7SJacob Faibussowitsch 96981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9699f108dbd7SJacob Faibussowitsch @*/ 9700d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9701d71ae5a4SJacob Faibussowitsch { 97026ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 97036ed19f2fSJacob Faibussowitsch PetscInt *idx; 97046ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9705f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 97066ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9707f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9708f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9709f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9710f108dbd7SJacob Faibussowitsch IS glob; 9711f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9712f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9713f108dbd7SJacob Faibussowitsch 9714f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9715f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9716ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 97174f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 97186bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 97199566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 97209566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 972163a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 97226ed19f2fSJacob Faibussowitsch { 97236ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 97246ed19f2fSJacob Faibussowitsch 97259566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9726f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9727f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9728f108dbd7SJacob Faibussowitsch 97299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 973098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9731f108dbd7SJacob Faibussowitsch } 97326ed19f2fSJacob Faibussowitsch } 9733f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97344f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 97359566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 97369566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 97379371c9d4SSatish Balay } else { 97389371c9d4SSatish Balay *OrthQualLabel = NULL; 97399371c9d4SSatish Balay } 97409566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97419566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 97429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 97439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 97449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 97459566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 97469566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 97479566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 97489566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 97499566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 97509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 97519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 97529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 97539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 97549566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 97559566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 97569566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 97579566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 97586ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 97596ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9760f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9761f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9762898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9763f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9764f108dbd7SJacob Faibussowitsch 97656ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9766f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9767f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 97689566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 97699566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9770f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 97719566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 97726ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 97736ed19f2fSJacob Faibussowitsch PetscInt i; 97746ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9775f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9776f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9777f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9778f108dbd7SJacob Faibussowitsch 9779f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9780f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 97819566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9782f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 97836ed19f2fSJacob Faibussowitsch { 97846ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 97856ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 97866ed19f2fSJacob Faibussowitsch 97879566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97889566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 97899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97906ed19f2fSJacob Faibussowitsch } 9791f108dbd7SJacob Faibussowitsch 9792f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9793f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9794f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9795f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9796f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9797addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9798addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9799addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9800f108dbd7SJacob Faibussowitsch } 9801addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9802addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9803addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9804f108dbd7SJacob Faibussowitsch 9805f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9806f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9807f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9808f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9809f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9810f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9811f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9812f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9813f108dbd7SJacob Faibussowitsch } 9814ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9815ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9816f108dbd7SJacob Faibussowitsch } 98179566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 98189566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9819f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 98206ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9821f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98229566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9823f108dbd7SJacob Faibussowitsch } 9824f108dbd7SJacob Faibussowitsch } 98259566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 98269566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 98279566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 98289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 98299566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 98309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9831f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98329566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9833f108dbd7SJacob Faibussowitsch } 98349566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9835cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 98369566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 98373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9838f108dbd7SJacob Faibussowitsch } 9839f108dbd7SJacob Faibussowitsch 9840d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 98411eb70e55SToby Isaac * interpolator construction */ 9842d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9843d71ae5a4SJacob Faibussowitsch { 98441eb70e55SToby Isaac PetscSection section, newSection, gsection; 98451eb70e55SToby Isaac PetscSF sf; 98461eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 98471eb70e55SToby Isaac 98481eb70e55SToby Isaac PetscFunctionBegin; 98491eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 98504f572ea9SToby Isaac PetscAssertPointer(odm, 2); 98519566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 98529566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9853712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 98541eb70e55SToby Isaac if (!ghasConstraints) { 98559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 98561eb70e55SToby Isaac *odm = dm; 98573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98581eb70e55SToby Isaac } 98599566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 98609566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 98619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 98629566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 9863eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 98649566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 98659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 98663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98671eb70e55SToby Isaac } 98681eb70e55SToby Isaac 9869d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9870d71ae5a4SJacob Faibussowitsch { 98711eb70e55SToby Isaac DM dmco, dmfo; 98721eb70e55SToby Isaac Mat interpo; 98731eb70e55SToby Isaac Vec rscale; 98741eb70e55SToby Isaac Vec cglobalo, clocal; 98751eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 98761eb70e55SToby Isaac PetscBool regular; 98771eb70e55SToby Isaac 98781eb70e55SToby Isaac PetscFunctionBegin; 98799566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 98809566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 98819566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 98829566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 98839566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 98849566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 98859566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 98869566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 98879566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 98889566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 98899566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98909566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98919566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98929566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98939566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98949566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98959566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98969566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98979566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98989566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 98999566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 99009566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 99019566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 99029566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 99031eb70e55SToby Isaac *shift = fglobal; 99049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 99059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 99069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 99079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 99089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 99099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 99109566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 99119566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 99123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99131eb70e55SToby Isaac } 99141eb70e55SToby Isaac 9915d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9916d71ae5a4SJacob Faibussowitsch { 99171eb70e55SToby Isaac PetscObject shifto; 99181eb70e55SToby Isaac Vec shift; 99191eb70e55SToby Isaac 99201eb70e55SToby Isaac PetscFunctionBegin; 99211eb70e55SToby Isaac if (!interp) { 99221eb70e55SToby Isaac Vec rscale; 99231eb70e55SToby Isaac 99249566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 99259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 99261eb70e55SToby Isaac } else { 99279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 99281eb70e55SToby Isaac } 99299566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 99301eb70e55SToby Isaac if (!shifto) { 99319566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 99329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 99331eb70e55SToby Isaac shifto = (PetscObject)shift; 99349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 99351eb70e55SToby Isaac } 99361eb70e55SToby Isaac shift = (Vec)shifto; 99379566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 99389566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 99399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 99403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 99411eb70e55SToby Isaac } 99421eb70e55SToby Isaac 9943bceba477SMatthew G. Knepley /* Pointwise interpolation 9944bceba477SMatthew G. Knepley Just code FEM for now 9945bceba477SMatthew G. Knepley u^f = I u^c 99464ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 99474ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 99484ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9949bceba477SMatthew G. Knepley */ 9950d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9951d71ae5a4SJacob Faibussowitsch { 9952bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9953bceba477SMatthew G. Knepley PetscInt m, n; 9954a063dac3SMatthew G. Knepley void *ctx; 995568132eb9SMatthew G. Knepley DM cdm; 9956cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9957bceba477SMatthew G. Knepley 9958bceba477SMatthew G. Knepley PetscFunctionBegin; 99599566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 99609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 99619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 99629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 996368132eb9SMatthew G. Knepley 99649566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 99659566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 99669566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 99679566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 99689566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 996968132eb9SMatthew G. Knepley 99709566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99719566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99729566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 99739566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 99749566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 99754db47ee9SStefano Zampini if (scaling) { 99765d1c2e58SMatthew G. Knepley /* Use naive scaling */ 99779566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 99784db47ee9SStefano Zampini } 99793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9980a063dac3SMatthew G. Knepley } 9981bceba477SMatthew G. Knepley 9982d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9983d71ae5a4SJacob Faibussowitsch { 99846dbf9973SLawrence Mitchell VecScatter ctx; 998590748bafSMatthew G. Knepley 9986a063dac3SMatthew G. Knepley PetscFunctionBegin; 99879566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 99889566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 99899566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9991bceba477SMatthew G. Knepley } 9992bceba477SMatthew G. Knepley 9993d71ae5a4SJacob 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[]) 9994d71ae5a4SJacob Faibussowitsch { 999500635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 999600635df3SMatthew G. Knepley PetscInt c; 999700635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99983e9753d6SMatthew G. Knepley } 99993e9753d6SMatthew G. Knepley 10000d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 10001d71ae5a4SJacob Faibussowitsch { 10002b4937a87SMatthew G. Knepley DM dmc; 10003b4937a87SMatthew G. Knepley PetscDS ds; 10004b4937a87SMatthew G. Knepley Vec ones, locmass; 10005b4937a87SMatthew G. Knepley IS cellIS; 10006b4937a87SMatthew G. Knepley PetscFormKey key; 10007b4937a87SMatthew G. Knepley PetscInt depth; 10008b4937a87SMatthew G. Knepley 10009b4937a87SMatthew G. Knepley PetscFunctionBegin; 100109566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 100119566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 100129566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 100139566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 100149566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 100159566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 100169566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 100179566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 100189566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 100199566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 100209566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10021b4937a87SMatthew G. Knepley key.label = NULL; 10022b4937a87SMatthew G. Knepley key.value = 0; 10023b4937a87SMatthew G. Knepley key.field = 0; 10024b4937a87SMatthew G. Knepley key.part = 0; 100259566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 100269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100279566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 100289566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 100299566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 100309566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 100319566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 100329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10034b4937a87SMatthew G. Knepley } 10035b4937a87SMatthew G. Knepley 10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10037d71ae5a4SJacob Faibussowitsch { 10038bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10039bd041c0cSMatthew G. Knepley PetscInt m, n; 10040bd041c0cSMatthew G. Knepley void *ctx; 10041bd041c0cSMatthew G. Knepley DM cdm; 10042bd041c0cSMatthew G. Knepley PetscBool regular; 10043bd041c0cSMatthew G. Knepley 10044bd041c0cSMatthew G. Knepley PetscFunctionBegin; 100453e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 100463e9753d6SMatthew G. Knepley DM dmc; 100473e9753d6SMatthew G. Knepley PetscDS ds; 10048b4937a87SMatthew G. Knepley PetscWeakForm wf; 100493e9753d6SMatthew G. Knepley Vec u; 100503e9753d6SMatthew G. Knepley IS cellIS; 1005106ad1575SMatthew G. Knepley PetscFormKey key; 100523e9753d6SMatthew G. Knepley PetscInt depth; 100533e9753d6SMatthew G. Knepley 100549566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 100559566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 100569566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 100579566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 100589566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 100599566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 100609566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 100618d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 100629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 100639566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 100649566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 100656528b96dSMatthew G. Knepley key.label = NULL; 100666528b96dSMatthew G. Knepley key.value = 0; 100676528b96dSMatthew G. Knepley key.field = 0; 1006806ad1575SMatthew G. Knepley key.part = 0; 100699566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 100709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 100718d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 100729566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 100733e9753d6SMatthew G. Knepley } else { 100749566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 100759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 100769566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 100779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10078bd041c0cSMatthew G. Knepley 100799566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 100809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 100819566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 100829566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10083bd041c0cSMatthew G. Knepley 100849566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 100859566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 100869566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 100879566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 100883e9753d6SMatthew G. Knepley } 100899566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10091bd041c0cSMatthew G. Knepley } 10092bd041c0cSMatthew G. Knepley 100930aef6b92SMatthew G. Knepley /*@ 100940aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100950aef6b92SMatthew G. Knepley 100960aef6b92SMatthew G. Knepley Input Parameter: 10097a1cb98faSBarry Smith . dm - The `DMPLEX` object 100980aef6b92SMatthew G. Knepley 100990aef6b92SMatthew G. Knepley Output Parameter: 101000aef6b92SMatthew G. Knepley . regular - The flag 101010aef6b92SMatthew G. Knepley 101020aef6b92SMatthew G. Knepley Level: intermediate 101030aef6b92SMatthew G. Knepley 101041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 101050aef6b92SMatthew G. Knepley @*/ 10106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10107d71ae5a4SJacob Faibussowitsch { 101080aef6b92SMatthew G. Knepley PetscFunctionBegin; 101090aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101104f572ea9SToby Isaac PetscAssertPointer(regular, 2); 101110aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 101123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101130aef6b92SMatthew G. Knepley } 101140aef6b92SMatthew G. Knepley 101150aef6b92SMatthew G. Knepley /*@ 101160aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 101170aef6b92SMatthew G. Knepley 101180aef6b92SMatthew G. Knepley Input Parameters: 10119a1cb98faSBarry Smith + dm - The `DMPLEX` object 101200aef6b92SMatthew G. Knepley - regular - The flag 101210aef6b92SMatthew G. Knepley 101220aef6b92SMatthew G. Knepley Level: intermediate 101230aef6b92SMatthew G. Knepley 101241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 101250aef6b92SMatthew G. Knepley @*/ 10126d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10127d71ae5a4SJacob Faibussowitsch { 101280aef6b92SMatthew G. Knepley PetscFunctionBegin; 101290aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101300aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 101313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 101320aef6b92SMatthew G. Knepley } 101330aef6b92SMatthew G. Knepley 10134a68b90caSToby Isaac /*@ 10135f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10136a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10137a68b90caSToby Isaac 10138a1cb98faSBarry Smith Not Collective 10139a68b90caSToby Isaac 10140f899ff85SJose E. Roman Input Parameter: 10141a1cb98faSBarry Smith . dm - The `DMPLEX` object 10142a68b90caSToby Isaac 10143a68b90caSToby Isaac Output Parameters: 1014420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1014520f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10146a68b90caSToby Isaac 10147a68b90caSToby Isaac Level: intermediate 10148a68b90caSToby Isaac 101491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10150a68b90caSToby Isaac @*/ 10151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10152d71ae5a4SJacob Faibussowitsch { 10153a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10154a68b90caSToby Isaac 10155a68b90caSToby Isaac PetscFunctionBegin; 10156a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101579566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10158a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10159a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 101603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10161a68b90caSToby Isaac } 10162a68b90caSToby Isaac 10163a68b90caSToby Isaac /*@ 10164a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10165a68b90caSToby Isaac 1016620f4b53cSBarry Smith Collective 10167a68b90caSToby Isaac 10168a68b90caSToby Isaac Input Parameters: 10169a1cb98faSBarry Smith + dm - The `DMPLEX` object 10170a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10171a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10172a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10173a68b90caSToby Isaac 10174a68b90caSToby Isaac Level: intermediate 10175a68b90caSToby Isaac 10176a1cb98faSBarry Smith Notes: 10177a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10178a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10179a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10180a4e35b19SJacob Faibussowitsch 10181a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10182a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10183a1cb98faSBarry Smith 1018420f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10185a1cb98faSBarry Smith 101861cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10187a68b90caSToby Isaac @*/ 10188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10189d71ae5a4SJacob Faibussowitsch { 10190a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10191e228b242SToby Isaac PetscMPIInt result; 10192a68b90caSToby Isaac 10193a68b90caSToby Isaac PetscFunctionBegin; 10194a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10195e228b242SToby Isaac if (anchorSection) { 10196e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101981dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10199e228b242SToby Isaac } 10200e228b242SToby Isaac if (anchorIS) { 10201e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 102029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 102031dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10204e228b242SToby Isaac } 10205a68b90caSToby Isaac 102069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 102079566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10208a68b90caSToby Isaac plex->anchorSection = anchorSection; 10209a68b90caSToby Isaac 102109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 102119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10212a68b90caSToby Isaac plex->anchorIS = anchorIS; 10213a68b90caSToby Isaac 10214cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10215a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10216a68b90caSToby Isaac const PetscInt *anchors; 10217a68b90caSToby Isaac 102189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 102199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 102209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10221a68b90caSToby Isaac for (a = 0; a < size; a++) { 10222a68b90caSToby Isaac PetscInt p; 10223a68b90caSToby Isaac 10224a68b90caSToby Isaac p = anchors[a]; 10225a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10226a68b90caSToby Isaac PetscInt dof; 10227a68b90caSToby Isaac 102289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10229a68b90caSToby Isaac if (dof) { 102309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1023163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10232a68b90caSToby Isaac } 10233a68b90caSToby Isaac } 10234a68b90caSToby Isaac } 102359566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10236a68b90caSToby Isaac } 10237f7c74593SToby Isaac /* reset the generic constraints */ 102389566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 102393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10240a68b90caSToby Isaac } 10241a68b90caSToby Isaac 10242d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10243d71ae5a4SJacob Faibussowitsch { 10244f7c74593SToby Isaac PetscSection anchorSection; 102456995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10246a68b90caSToby Isaac 10247a68b90caSToby Isaac PetscFunctionBegin; 10248a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102499566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 102509566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 102519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102526995de1eSToby Isaac if (numFields) { 10253719ab38cSToby Isaac PetscInt f; 102549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10255719ab38cSToby Isaac 10256719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10257719ab38cSToby Isaac PetscInt numComp; 10258719ab38cSToby Isaac 102599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 102609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10261719ab38cSToby Isaac } 102626995de1eSToby Isaac } 102639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 102649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102656995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 102666995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 102676995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 102689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10269a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 102709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10271a68b90caSToby Isaac if (dof) { 102729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 102739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10274a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 102759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 102769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10277a68b90caSToby Isaac } 10278a68b90caSToby Isaac } 10279a68b90caSToby Isaac } 102809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 102819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 102823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10283a68b90caSToby Isaac } 10284a68b90caSToby Isaac 10285d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10286d71ae5a4SJacob Faibussowitsch { 10287f7c74593SToby Isaac PetscSection aSec; 10288ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 102890ac89760SToby Isaac const PetscInt *anchors; 102900ac89760SToby Isaac PetscInt numFields, f; 1029166ad2231SToby Isaac IS aIS; 10292e19f7ee6SMark Adams MatType mtype; 10293e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102940ac89760SToby Isaac 102950ac89760SToby Isaac PetscFunctionBegin; 102960ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 102999566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 103009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 103019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 103029566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 103039566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 103049566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10305e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10306e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10307e19f7ee6SMark Adams else mtype = MATSEQAIJ; 103089566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 103099566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 103109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 103116995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 103129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 103139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 103149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 103150ac89760SToby Isaac i[0] = 0; 103169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 103170ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10318f19733c5SToby Isaac PetscInt rDof, rOff, r; 10319f19733c5SToby Isaac 103209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10321f19733c5SToby Isaac if (!rDof) continue; 103229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103230ac89760SToby Isaac if (numFields) { 103240ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103250ac89760SToby Isaac annz = 0; 10326f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10327f19733c5SToby Isaac a = anchors[rOff + r]; 10328ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103300ac89760SToby Isaac annz += aDof; 103310ac89760SToby Isaac } 103329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10334ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103350ac89760SToby Isaac } 103362f7452b8SBarry Smith } else { 103370ac89760SToby Isaac annz = 0; 103389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103390ac89760SToby Isaac for (q = 0; q < dof; q++) { 10340ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10341ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103430ac89760SToby Isaac annz += aDof; 103440ac89760SToby Isaac } 103459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10347ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 103480ac89760SToby Isaac } 103490ac89760SToby Isaac } 103500ac89760SToby Isaac nnz = i[m]; 103519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 103520ac89760SToby Isaac offset = 0; 103530ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 103540ac89760SToby Isaac if (numFields) { 103550ac89760SToby Isaac for (f = 0; f < numFields; f++) { 103569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 103570ac89760SToby Isaac for (q = 0; q < dof; q++) { 103580ac89760SToby Isaac PetscInt rDof, rOff, r; 103599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103610ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103620ac89760SToby Isaac PetscInt s; 103630ac89760SToby Isaac 103640ac89760SToby Isaac a = anchors[rOff + r]; 10365ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 103679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10368ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103690ac89760SToby Isaac } 103700ac89760SToby Isaac } 103710ac89760SToby Isaac } 103722f7452b8SBarry Smith } else { 103739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 103740ac89760SToby Isaac for (q = 0; q < dof; q++) { 103750ac89760SToby Isaac PetscInt rDof, rOff, r; 103769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 103779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 103780ac89760SToby Isaac for (r = 0; r < rDof; r++) { 103790ac89760SToby Isaac PetscInt s; 103800ac89760SToby Isaac 103810ac89760SToby Isaac a = anchors[rOff + r]; 10382ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 103839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 103849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10385ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 103860ac89760SToby Isaac } 103870ac89760SToby Isaac } 103880ac89760SToby Isaac } 103890ac89760SToby Isaac } 103909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103919566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103929566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103950ac89760SToby Isaac } 103960ac89760SToby Isaac 10397d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10398d71ae5a4SJacob Faibussowitsch { 10399f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10400f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1040166ad2231SToby Isaac Mat cMat; 1040266ad2231SToby Isaac 1040366ad2231SToby Isaac PetscFunctionBegin; 1040466ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 104059566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1040666ad2231SToby Isaac if (anchorSection) { 1040744a7f3ddSMatthew G. Knepley PetscInt Nf; 10408e228b242SToby Isaac 104099566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 104109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 104119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 104129566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 104139566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 104149566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 104159566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 104169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1041766ad2231SToby Isaac } 104183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1041966ad2231SToby Isaac } 10420a93c429eSMatthew G. Knepley 10421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10422d71ae5a4SJacob Faibussowitsch { 10423a93c429eSMatthew G. Knepley IS subis; 10424a93c429eSMatthew G. Knepley PetscSection section, subsection; 10425a93c429eSMatthew G. Knepley 10426a93c429eSMatthew G. Knepley PetscFunctionBegin; 104279566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1042828b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1042928b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10430a93c429eSMatthew G. Knepley /* Create subdomain */ 10431*30cbcd5dSksagiyam PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, NULL, subdm)); 10432a93c429eSMatthew G. Knepley /* Create submodel */ 104339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 104349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 104359566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 104369566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 104379566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10438a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10439a93c429eSMatthew G. Knepley if (is) { 10440a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10441a93c429eSMatthew G. Knepley IS spIS; 10442a93c429eSMatthew G. Knepley const PetscInt *spmap; 10443a93c429eSMatthew G. Knepley PetscInt *subIndices; 10444a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10445a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10446a93c429eSMatthew G. Knepley 104479566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 104489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 104499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 104509566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 104519566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 104529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10453a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10454a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10455a93c429eSMatthew G. Knepley 104569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10457a93c429eSMatthew G. Knepley if (gdof > 0) { 10458a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10459a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10460a93c429eSMatthew G. Knepley 104619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 104629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10463a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10464a93c429eSMatthew G. Knepley } 10465a93c429eSMatthew G. Knepley subSize += pSubSize; 10466a93c429eSMatthew G. Knepley if (pSubSize) { 10467a93c429eSMatthew G. Knepley if (bs < 0) { 10468a93c429eSMatthew G. Knepley bs = pSubSize; 10469a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10470a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10471a93c429eSMatthew G. Knepley bs = 1; 10472a93c429eSMatthew G. Knepley } 10473a93c429eSMatthew G. Knepley } 10474a93c429eSMatthew G. Knepley } 10475a93c429eSMatthew G. Knepley } 10476a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 104779371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 104789371c9d4SSatish Balay bsLocal[1] = bs; 104799566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 104809371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 104819371c9d4SSatish Balay bs = 1; 104829371c9d4SSatish Balay } else { 104839371c9d4SSatish Balay bs = bsMinMax[0]; 104849371c9d4SSatish Balay } 104859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10486a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10487a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10488a93c429eSMatthew G. Knepley 104899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10490a93c429eSMatthew G. Knepley if (gdof > 0) { 10491a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10492a93c429eSMatthew G. Knepley 104939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10494a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10495a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10496a93c429eSMatthew G. Knepley 10497a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10498a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 104999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 105009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10501a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10502a93c429eSMatthew G. Knepley } 105039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 105049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10505ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10506a93c429eSMatthew G. Knepley } 10507a93c429eSMatthew G. Knepley } 10508a93c429eSMatthew G. Knepley } 105099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 105109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10511a93c429eSMatthew G. Knepley if (bs > 1) { 10512a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10513a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10514a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10515a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 105169371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 105179371c9d4SSatish Balay set = 0; 105189371c9d4SSatish Balay break; 105199371c9d4SSatish Balay } 10520a93c429eSMatthew G. Knepley } 10521a93c429eSMatthew G. Knepley } 105229566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10523a93c429eSMatthew G. Knepley } 10524a93c429eSMatthew G. Knepley /* Attach nullspace */ 10525a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10526a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10527a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10528a93c429eSMatthew G. Knepley } 10529a93c429eSMatthew G. Knepley if (f < Nf) { 10530a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 105319566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 105326823f3c5SBlaise Bourdin 105339566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 105349566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10535a93c429eSMatthew G. Knepley } 10536a93c429eSMatthew G. Knepley } 105373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10538a93c429eSMatthew G. Knepley } 10539c0f0dcc3SMatthew G. Knepley 10540c0f0dcc3SMatthew G. Knepley /*@ 10541c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10542c0f0dcc3SMatthew G. Knepley 10543a1cb98faSBarry Smith Input Parameters: 10544a1cb98faSBarry Smith + dm - The `DM` 10545a1cb98faSBarry Smith - dummy - unused argument 10546a1cb98faSBarry Smith 10547a1cb98faSBarry Smith Options Database Key: 10548a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10549c0f0dcc3SMatthew G. Knepley 10550c0f0dcc3SMatthew G. Knepley Level: developer 10551c0f0dcc3SMatthew G. Knepley 105521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10553c0f0dcc3SMatthew G. Knepley @*/ 10554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10555d71ae5a4SJacob Faibussowitsch { 10556b665b14eSToby Isaac PetscLogHandler default_handler; 10557b665b14eSToby Isaac 105582611ad71SToby Isaac PetscFunctionBegin; 105592611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10560b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10561b665b14eSToby Isaac if (default_handler) { 10562c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10563c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10564c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10565c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10566c0f0dcc3SMatthew G. Knepley const char *name; 10567c0f0dcc3SMatthew G. Knepley 105689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 105699566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 105709566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 105719566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10572b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10573c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10574c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10575c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1057663a3b9bcSJacob 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))); 105772611ad71SToby Isaac } else { 10578b665b14eSToby 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."); 105792611ad71SToby Isaac } 105803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10581c0f0dcc3SMatthew G. Knepley } 10582