1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h> 3af0996ceSBarry Smith #include <petsc/private/isimpl.h> 4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h> 58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h> 60c312b8eSJed Brown #include <petscsf.h> 7e228b242SToby Isaac #include <petscds.h> 8e412dcbdSMatthew G. Knepley #include <petscdraw.h> 9f19dbd58SToby Isaac #include <petscdmfield.h> 10012bc364SMatthew G. Knepley #include <petscdmplextransform.h> 11552f7358SJed Brown 12552f7358SJed Brown /* Logging support */ 1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad; 14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 15552f7358SJed Brown 16f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 17f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 18f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 19f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 20f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 21f39ec787SMatthew G. Knepley "volume = {38},\n" 22f39ec787SMatthew G. Knepley "number = {5},\n" 23f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 24f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 25f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 26f39ec787SMatthew G. Knepley "year = {2016},\n" 27f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 28f39ec787SMatthew G. Knepley 295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 30552f7358SJed Brown 31e5337592SStefano Zampini /*@ 329318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 339318fe57SMatthew G. Knepley 349318fe57SMatthew G. Knepley Input Parameter: 35a1cb98faSBarry Smith . dm - The `DMPLEX` object 369318fe57SMatthew G. Knepley 379318fe57SMatthew G. Knepley Output Parameter: 389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 399318fe57SMatthew G. Knepley 409318fe57SMatthew G. Knepley Level: intermediate 419318fe57SMatthew G. Knepley 42a1cb98faSBarry Smith Note: 43a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 44a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 45a1cb98faSBarry Smith 461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 479318fe57SMatthew G. Knepley @*/ 48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 49d71ae5a4SJacob Faibussowitsch { 509318fe57SMatthew G. Knepley DMPolytopeType ct; 519318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 529318fe57SMatthew G. Knepley 539318fe57SMatthew G. Knepley PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 559371c9d4SSatish Balay if (cEnd <= cStart) { 569371c9d4SSatish Balay *simplex = PETSC_FALSE; 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 589371c9d4SSatish Balay } 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 609318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 629318fe57SMatthew G. Knepley } 639318fe57SMatthew G. Knepley 649318fe57SMatthew G. Knepley /*@ 65412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 66e5337592SStefano Zampini 67d8d19677SJose E. Roman Input Parameters: 68a1cb98faSBarry Smith + dm - The `DMPLEX` object 69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 70e5337592SStefano Zampini 71e5337592SStefano Zampini Output Parameters: 72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7340196513SBarry Smith - cEnd - The upper bound on "normal" cells 74e5337592SStefano Zampini 75412e9a14SMatthew G. Knepley Level: developer 76e5337592SStefano Zampini 77a1cb98faSBarry Smith Note: 785ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 79a1cb98faSBarry Smith 802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 81e5337592SStefano Zampini @*/ 82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 83d71ae5a4SJacob Faibussowitsch { 845ae96e2bSMatthew G. Knepley DMLabel ctLabel; 855ae96e2bSMatthew G. Knepley IS valueIS; 865ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 875ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 88e5337592SStefano Zampini 89e5337592SStefano Zampini PetscFunctionBegin; 909566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 915ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 925ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 935ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 945ae96e2bSMatthew G. Knepley if (!Nct) cS = cE = 0; 955ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 96c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 975ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 985ae96e2bSMatthew G. Knepley 995ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1005ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1015ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1025ae96e2bSMatthew G. Knepley break; 1035ae96e2bSMatthew G. Knepley } 104c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1055ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1065ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1075ae96e2bSMatthew G. Knepley // Check that a point has the right height 1085ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1095ae96e2bSMatthew G. Knepley if (ht != height) continue; 1105ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1115ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1125ae96e2bSMatthew G. Knepley } 1135ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 114695799ffSMatthew G. Knepley // Reset label for fast lookup 115695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 116412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 117412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119e5337592SStefano Zampini } 120e5337592SStefano Zampini 1219c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1229c600e38SMatt McGurn { 1239c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1249c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1259c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1269c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1279c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1289c600e38SMatt McGurn 1299c600e38SMatt McGurn PetscFunctionBegin; 1309c600e38SMatt McGurn 1319c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1329c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1339c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1349c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1359c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1369c600e38SMatt McGurn if (field >= 0) { 1379c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1389c600e38SMatt McGurn } else { 1399c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1409c600e38SMatt McGurn } 1419c600e38SMatt McGurn 1429c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1439c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1449c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1459c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1469c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1479c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1489c600e38SMatt McGurn PetscInt dep; 1499c600e38SMatt McGurn 1509c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1519c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1529c600e38SMatt McGurn if (pStart >= 0) { 1539c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1549c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1559c600e38SMatt McGurn } 1569c600e38SMatt McGurn if (field >= 0) { 1579c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1589c600e38SMatt McGurn } else { 1599c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1609c600e38SMatt McGurn } 1619c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1629c600e38SMatt McGurn } 1639c600e38SMatt McGurn 1649c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1659c600e38SMatt McGurn *types = 0; 1669c600e38SMatt McGurn 1679c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1689c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1699c600e38SMatt McGurn } 1709c600e38SMatt McGurn 1719c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1729c600e38SMatt McGurn t = 0; 1739c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1749c600e38SMatt McGurn sStart[t] = vStart; 1759c600e38SMatt McGurn sEnd[t] = vEnd; 1769c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1779c600e38SMatt McGurn ++t; 1789c600e38SMatt McGurn } 1799c600e38SMatt McGurn 1809c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1819c600e38SMatt McGurn if (globalvcdof[c]) { 1829c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1839c600e38SMatt McGurn 1849c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1859c600e38SMatt McGurn sStart[t] = cStart; 1869c600e38SMatt McGurn sEnd[t] = cEnd; 1879c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1889c600e38SMatt McGurn ++t; 1899c600e38SMatt McGurn } 1909c600e38SMatt McGurn } 1919c600e38SMatt McGurn 1929c600e38SMatt McGurn if (!(*types)) { 1939c600e38SMatt McGurn if (field >= 0) { 1949c600e38SMatt McGurn const char *fieldname; 1959c600e38SMatt McGurn 1969c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1979c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1989c600e38SMatt McGurn } else { 1999c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 2009c600e38SMatt McGurn } 2019c600e38SMatt McGurn } 2029c600e38SMatt McGurn 2039c600e38SMatt McGurn *ssStart = sStart; 2049c600e38SMatt McGurn *ssEnd = sEnd; 2059c600e38SMatt McGurn *sft = ft; 2069c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2079c600e38SMatt McGurn } 2089c600e38SMatt McGurn 2099c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2109c600e38SMatt McGurn { 2119c600e38SMatt McGurn PetscFunctionBegin; 2129c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2139c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2149c600e38SMatt McGurn } 2159c600e38SMatt McGurn 216d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 217d71ae5a4SJacob Faibussowitsch { 218412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 219a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2207e42fee7SMatthew G. Knepley 2217e42fee7SMatthew G. Knepley PetscFunctionBegin; 222e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2259566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2277e42fee7SMatthew G. Knepley if (field >= 0) { 2289566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2299566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2307e42fee7SMatthew G. Knepley } else { 2319566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2329566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2337e42fee7SMatthew G. Knepley } 234712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 235a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2367e42fee7SMatthew G. Knepley *sStart = vStart; 2377e42fee7SMatthew G. Knepley *sEnd = vEnd; 238f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2397e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 240a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2417e42fee7SMatthew G. Knepley *sStart = cStart; 2427e42fee7SMatthew G. Knepley *sEnd = cEnd; 243f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2447e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 245e630c359SToby Isaac } else { 246e630c359SToby Isaac if (field >= 0) { 247e630c359SToby Isaac const char *fieldname; 248e630c359SToby Isaac 2499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 25063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 251e630c359SToby Isaac } else { 25263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 253e630c359SToby Isaac } 254e630c359SToby Isaac } 2553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2567e42fee7SMatthew G. Knepley } 2577e42fee7SMatthew G. Knepley 2586913077dSMatthew G. Knepley /*@ 2596913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2606913077dSMatthew G. Knepley 26120f4b53cSBarry Smith Collective 2626913077dSMatthew G. Knepley 2636913077dSMatthew G. Knepley Input Parameters: 264a1cb98faSBarry Smith + dm - The `DMPLEX` object 2656913077dSMatthew G. Knepley . n - The number of vectors 2666913077dSMatthew G. Knepley . u - The array of local vectors 267a1cb98faSBarry Smith - viewer - The `PetscViewer` 2686913077dSMatthew G. Knepley 2696913077dSMatthew G. Knepley Level: advanced 2706913077dSMatthew G. Knepley 2711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2726913077dSMatthew G. Knepley @*/ 273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 274d71ae5a4SJacob Faibussowitsch { 2756913077dSMatthew G. Knepley PetscDS ds; 2766913077dSMatthew G. Knepley PetscDraw draw = NULL; 2776913077dSMatthew G. Knepley PetscDrawLG lg; 2786913077dSMatthew G. Knepley Vec coordinates; 2796913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2806913077dSMatthew G. Knepley PetscReal *vals; 2816913077dSMatthew G. Knepley PetscInt *Nc; 2826913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2836913077dSMatthew G. Knepley char **names; 2846913077dSMatthew G. Knepley 2856913077dSMatthew G. Knepley PetscFunctionBegin; 2869566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2879566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2889566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2899566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2906913077dSMatthew G. Knepley 2919566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2923ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2939566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2946913077dSMatthew G. Knepley 2959566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2966913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2976913077dSMatthew G. Knepley const char *vname; 2986913077dSMatthew G. Knepley 2999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 3006913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3016913077dSMatthew G. Knepley PetscObject disc; 3026913077dSMatthew G. Knepley const char *fname; 3036913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3046913077dSMatthew G. Knepley 3059566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3066913077dSMatthew G. Knepley /* TODO Create names for components */ 3076913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 309c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 310c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 311c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3129566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3136913077dSMatthew G. Knepley } 3146913077dSMatthew G. Knepley } 3156913077dSMatthew G. Knepley } 3169566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3176913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3219566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3226913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3236913077dSMatthew G. Knepley PetscScalar *x, *svals; 3246913077dSMatthew G. Knepley 3259566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3266913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3279566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3286913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3296913077dSMatthew G. Knepley } 3309566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3316913077dSMatthew G. Knepley } 3329566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3339566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3349566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3359566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3366913077dSMatthew G. Knepley 3379566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3406913077dSMatthew G. Knepley } 3416913077dSMatthew G. Knepley 342d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 343d71ae5a4SJacob Faibussowitsch { 3446913077dSMatthew G. Knepley DM dm; 3456913077dSMatthew G. Knepley 3466913077dSMatthew G. Knepley PetscFunctionBegin; 3479566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3489566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3506913077dSMatthew G. Knepley } 3516913077dSMatthew G. Knepley 352d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 353d71ae5a4SJacob Faibussowitsch { 354e412dcbdSMatthew G. Knepley DM dm; 355d1df6f1dSMatthew G. Knepley PetscSection s; 356e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 357e412dcbdSMatthew G. Knepley DM cdm; 358e412dcbdSMatthew G. Knepley PetscSection coordSection; 359e412dcbdSMatthew G. Knepley Vec coordinates; 360c9c77995SMatthew G. Knepley const PetscScalar *array; 361c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 362339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3636913077dSMatthew G. Knepley PetscBool flg; 364d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 365e412dcbdSMatthew G. Knepley const char *name; 366339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 367e412dcbdSMatthew G. Knepley 368e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3699566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3709566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3729566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3749566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3789566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 380e412dcbdSMatthew G. Knepley 3819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3829566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 383e412dcbdSMatthew G. Knepley 3849566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 385c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3869566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 387e412dcbdSMatthew G. Knepley 388d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 389d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 390d1df6f1dSMatthew G. Knepley DM fdm = dm; 391d1df6f1dSMatthew G. Knepley Vec fv = v; 392d1df6f1dSMatthew G. Knepley IS fis; 393d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 394d1df6f1dSMatthew G. Knepley const char *fname; 395d1df6f1dSMatthew G. Knepley 3969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 398d1df6f1dSMatthew G. Knepley 3999566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 400ad540459SPierre Jolivet else prefix[0] = '\0'; 401d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4029566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4039566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4049566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4059566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 406d1df6f1dSMatthew G. Knepley } 407d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 408d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 409d1df6f1dSMatthew G. Knepley 4109566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 41163a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41263a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4139566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 414d1df6f1dSMatthew G. Knepley 415d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4169566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 417339e3443SMatthew G. Knepley if (!flg) { 4189566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4199566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 420d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 421339e3443SMatthew G. Knepley } 422c9c77995SMatthew G. Knepley 4239566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4249566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 425c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 427e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 42899a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 429c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 430c9c77995SMatthew G. Knepley PetscBool isDG; 431e56f9228SJed Brown PetscInt numCoords, color[4] = {-1, -1, -1, -1}; 432e412dcbdSMatthew G. Knepley 4339566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 434339e3443SMatthew G. Knepley if (a) { 435d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 436339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 437339e3443SMatthew G. Knepley } else { 438339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 439339e3443SMatthew G. Knepley PetscInt numVals, va; 440339e3443SMatthew G. Knepley 4419566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 44263a3b9bcSJacob Faibussowitsch PetscCheck(numVals % Nc == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals); 443d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 444d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 445d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 446d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 447339e3443SMatthew G. Knepley break; 448d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 449d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 450d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / (Nc * 2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp + numVals / (Nc * 2)]), vbound[0], vbound[1]); 451d1df6f1dSMatthew G. Knepley break; 452d71ae5a4SJacob Faibussowitsch default: 453d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 454339e3443SMatthew G. Knepley } 4559566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 456339e3443SMatthew G. Knepley } 457c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 458e412dcbdSMatthew G. Knepley switch (numCoords) { 459e412dcbdSMatthew G. Knepley case 6: 4609edc3542SMatthew Knepley case 12: /* Localized triangle */ 4619566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 462e412dcbdSMatthew G. Knepley break; 463e412dcbdSMatthew G. Knepley case 8: 4649edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 4659566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2])); 4669566063dSJacob Faibussowitsch PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0])); 467e412dcbdSMatthew G. Knepley break; 468d71ae5a4SJacob Faibussowitsch default: 469d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 470e412dcbdSMatthew G. Knepley } 471c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 472e412dcbdSMatthew G. Knepley } 4739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4749566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4759566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4769566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 477d1df6f1dSMatthew G. Knepley } 478d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4799566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 4819566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 482d1df6f1dSMatthew G. Knepley } 483d1df6f1dSMatthew G. Knepley } 4843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 485e412dcbdSMatthew G. Knepley } 486e412dcbdSMatthew G. Knepley 487d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 488d71ae5a4SJacob Faibussowitsch { 4896913077dSMatthew G. Knepley DM dm; 4906913077dSMatthew G. Knepley PetscDraw draw; 4916913077dSMatthew G. Knepley PetscInt dim; 4926913077dSMatthew G. Knepley PetscBool isnull; 4936913077dSMatthew G. Knepley 4946913077dSMatthew G. Knepley PetscFunctionBegin; 4959566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 4969566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 4973ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 4986913077dSMatthew G. Knepley 4999566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5016913077dSMatthew G. Knepley switch (dim) { 502d71ae5a4SJacob Faibussowitsch case 1: 503d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 504d71ae5a4SJacob Faibussowitsch break; 505d71ae5a4SJacob Faibussowitsch case 2: 506d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 507d71ae5a4SJacob Faibussowitsch break; 508d71ae5a4SJacob Faibussowitsch default: 509d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5106913077dSMatthew G. Knepley } 5113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5126913077dSMatthew G. Knepley } 5136913077dSMatthew G. Knepley 514d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 515d71ae5a4SJacob Faibussowitsch { 516684b87d9SLisandro Dalcin DM dm; 517684b87d9SLisandro Dalcin Vec locv; 518684b87d9SLisandro Dalcin const char *name; 519684b87d9SLisandro Dalcin PetscSection section; 520684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 521e630c359SToby Isaac PetscInt numFields; 522684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 523684b87d9SLisandro Dalcin 524684b87d9SLisandro Dalcin PetscFunctionBegin; 5259566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5269566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5299566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5309566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 532e630c359SToby Isaac if (!numFields) { 5339566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5349566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 535e630c359SToby Isaac } else { 536e630c359SToby Isaac PetscInt f; 537e630c359SToby Isaac 538e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5399566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 540e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5429566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 543e630c359SToby Isaac } 5449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 545e630c359SToby Isaac } 5463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 547684b87d9SLisandro Dalcin } 548684b87d9SLisandro Dalcin 549d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 550d71ae5a4SJacob Faibussowitsch { 551552f7358SJed Brown DM dm; 5525f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 553552f7358SJed Brown 554552f7358SJed Brown PetscFunctionBegin; 5559566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 55628b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5615f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5625f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 563684b87d9SLisandro Dalcin PetscInt i, numFields; 564684b87d9SLisandro Dalcin PetscObject fe; 565ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 566684b87d9SLisandro Dalcin Vec locv = v; 567684b87d9SLisandro Dalcin const char *name; 568684b87d9SLisandro Dalcin PetscInt step; 569684b87d9SLisandro Dalcin PetscReal time; 570ef31f671SMatthew G. Knepley 5719566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 572684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5739566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5749371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5759371c9d4SSatish Balay fem = PETSC_TRUE; 5769371c9d4SSatish Balay break; 5779371c9d4SSatish Balay } 578ef31f671SMatthew G. Knepley } 579684b87d9SLisandro Dalcin if (fem) { 580798534f6SMatthew G. Knepley PetscObject isZero; 581798534f6SMatthew G. Knepley 5829566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 5869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 5879566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5889566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 5899566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 590ef31f671SMatthew G. Knepley } 591552f7358SJed Brown if (isvtk) { 5929566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 593b136c2c9SMatthew G. Knepley } else if (ishdf5) { 594b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 5959566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 596b136c2c9SMatthew G. Knepley #else 597b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 598b136c2c9SMatthew G. Knepley #endif 599f13a32a3SMatthew G. Knepley } else if (isdraw) { 6009566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 601684b87d9SLisandro Dalcin } else if (isglvis) { 6029566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6039566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6049566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6055f34f2dcSJed Brown } else if (iscgns) { 6065f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6075f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6085f34f2dcSJed Brown #else 6095f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6105f34f2dcSJed Brown #endif 611684b87d9SLisandro Dalcin } 612798534f6SMatthew G. Knepley if (fem) { 6139566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6149566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 615798534f6SMatthew G. Knepley } 616552f7358SJed Brown } else { 617684b87d9SLisandro Dalcin PetscBool isseq; 618684b87d9SLisandro Dalcin 6199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6209566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6219566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 622552f7358SJed Brown } 6233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 624552f7358SJed Brown } 625552f7358SJed Brown 626d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 627d71ae5a4SJacob Faibussowitsch { 628552f7358SJed Brown DM dm; 6295f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 630552f7358SJed Brown 631552f7358SJed Brown PetscFunctionBegin; 6329566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 63328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6359566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6385f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6405f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 641552f7358SJed Brown Vec locv; 642798534f6SMatthew G. Knepley PetscObject isZero; 643552f7358SJed Brown const char *name; 644552f7358SJed Brown 6459566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6499566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6509566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6529566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6539566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6549566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 655b136c2c9SMatthew G. Knepley } else if (ishdf5) { 656b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6579566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 658b136c2c9SMatthew G. Knepley #else 659b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 660b136c2c9SMatthew G. Knepley #endif 6616823f3c5SBlaise Bourdin } else if (isexodusii) { 6626823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6639566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6646823f3c5SBlaise Bourdin #else 6656823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6666823f3c5SBlaise Bourdin #endif 667552f7358SJed Brown } else { 668684b87d9SLisandro Dalcin PetscBool isseq; 669684b87d9SLisandro Dalcin 6709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6719566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6729566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 673552f7358SJed Brown } 6743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 675552f7358SJed Brown } 676552f7358SJed Brown 677d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 678d71ae5a4SJacob Faibussowitsch { 679d930f514SMatthew G. Knepley DM dm; 680d930f514SMatthew G. Knepley MPI_Comm comm; 681d930f514SMatthew G. Knepley PetscViewerFormat format; 682d930f514SMatthew G. Knepley Vec v; 683d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 684d930f514SMatthew G. Knepley 685d930f514SMatthew G. Knepley PetscFunctionBegin; 6869566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 6879566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 68828b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 6909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 692d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 693a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 694a8ad634aSStefano Zampini /* this need a better fix */ 695a8ad634aSStefano Zampini if (dm->useNatural) { 696a8ad634aSStefano Zampini if (dm->sfNatural) { 697d930f514SMatthew G. Knepley const char *vecname; 698d930f514SMatthew G. Knepley PetscInt n, nroots; 699d930f514SMatthew G. Knepley 7009566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 7019566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 702d930f514SMatthew G. Knepley if (n == nroots) { 703f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7049566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7059566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7069566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 708d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 709d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 710a8ad634aSStefano Zampini } else v = originalv; 711a8ad634aSStefano Zampini } else v = originalv; 712a8ad634aSStefano Zampini 713d930f514SMatthew G. Knepley if (ishdf5) { 714d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7159566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 716d930f514SMatthew G. Knepley #else 717d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 718d930f514SMatthew G. Knepley #endif 719d930f514SMatthew G. Knepley } else if (isvtk) { 720d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 721d930f514SMatthew G. Knepley } else { 722d930f514SMatthew G. Knepley PetscBool isseq; 723d930f514SMatthew G. Knepley 7249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7259566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7269566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 727d930f514SMatthew G. Knepley } 728f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 730d930f514SMatthew G. Knepley } 731d930f514SMatthew G. Knepley 732d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 733d71ae5a4SJacob Faibussowitsch { 7342c40f234SMatthew G. Knepley DM dm; 7352c40f234SMatthew G. Knepley PetscBool ishdf5; 7362c40f234SMatthew G. Knepley 7372c40f234SMatthew G. Knepley PetscFunctionBegin; 7389566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 73928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7412c40f234SMatthew G. Knepley if (ishdf5) { 7422c40f234SMatthew G. Knepley DM dmBC; 7432c40f234SMatthew G. Knepley Vec gv; 7442c40f234SMatthew G. Knepley const char *name; 7452c40f234SMatthew G. Knepley 7469566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7479566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7509566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7519566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7529566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7539566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7541baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7562c40f234SMatthew G. Knepley } 7572c40f234SMatthew G. Knepley 758d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 759d71ae5a4SJacob Faibussowitsch { 7602c40f234SMatthew G. Knepley DM dm; 7616823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7622c40f234SMatthew G. Knepley 7632c40f234SMatthew G. Knepley PetscFunctionBegin; 7649566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76528b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7682c40f234SMatthew G. Knepley if (ishdf5) { 769878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7709566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 771b136c2c9SMatthew G. Knepley #else 772b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 773878b459fSMatthew G. Knepley #endif 7746823f3c5SBlaise Bourdin } else if (isexodusii) { 7756823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7769566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7776823f3c5SBlaise Bourdin #else 7786823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 7796823f3c5SBlaise Bourdin #endif 7801baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 782552f7358SJed Brown } 783552f7358SJed Brown 784d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 785d71ae5a4SJacob Faibussowitsch { 786d930f514SMatthew G. Knepley DM dm; 787d930f514SMatthew G. Knepley PetscViewerFormat format; 788d930f514SMatthew G. Knepley PetscBool ishdf5; 789d930f514SMatthew G. Knepley 790d930f514SMatthew G. Knepley PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 79228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7939566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 795d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 796a8ad634aSStefano Zampini if (dm->useNatural) { 797d930f514SMatthew G. Knepley if (dm->sfNatural) { 798d930f514SMatthew G. Knepley if (ishdf5) { 799d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 800d930f514SMatthew G. Knepley Vec v; 801d930f514SMatthew G. Knepley const char *vecname; 802d930f514SMatthew G. Knepley 803f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8069566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8079566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8089566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 809f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 810d930f514SMatthew G. Knepley #else 811d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 812d930f514SMatthew G. Knepley #endif 813d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 814d930f514SMatthew G. Knepley } 8151baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 816d930f514SMatthew G. Knepley } 8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 818d930f514SMatthew G. Knepley } 819d930f514SMatthew G. Knepley 820d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 821d71ae5a4SJacob Faibussowitsch { 822731e8ddeSMatthew G. Knepley PetscSection coordSection; 823731e8ddeSMatthew G. Knepley Vec coordinates; 824ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 825731e8ddeSMatthew G. Knepley const char *name[4]; 826731e8ddeSMatthew G. Knepley const PetscScalar *a; 827731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 828731e8ddeSMatthew G. Knepley 829731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 838731e8ddeSMatthew G. Knepley name[0] = "vertex"; 839731e8ddeSMatthew G. Knepley name[1] = "edge"; 840731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 841731e8ddeSMatthew G. Knepley name[dim] = "cell"; 842731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 843731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 844ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 845731e8ddeSMatthew G. Knepley 8469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 84763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 850731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 851731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 852731e8ddeSMatthew G. Knepley 853731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 855731e8ddeSMatthew G. Knepley if (!dof) continue; 8569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 85863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 859731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 861731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8629566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 864731e8ddeSMatthew G. Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 866731e8ddeSMatthew G. Knepley } 8679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 868731e8ddeSMatthew G. Knepley } 8699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 871731e8ddeSMatthew G. Knepley } 8729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 874731e8ddeSMatthew G. Knepley } 875731e8ddeSMatthew G. Knepley 8769371c9d4SSatish Balay typedef enum { 8779371c9d4SSatish Balay CS_CARTESIAN, 8789371c9d4SSatish Balay CS_POLAR, 8799371c9d4SSatish Balay CS_CYLINDRICAL, 8809371c9d4SSatish Balay CS_SPHERICAL 8819371c9d4SSatish Balay } CoordSystem; 88219ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 88319ad8254SMatthew G. Knepley 884d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 885d71ae5a4SJacob Faibussowitsch { 88619ad8254SMatthew G. Knepley PetscInt i; 88719ad8254SMatthew G. Knepley 88819ad8254SMatthew G. Knepley PetscFunctionBegin; 88919ad8254SMatthew G. Knepley if (dim > 3) { 8909566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 89119ad8254SMatthew G. Knepley } else { 892bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 89319ad8254SMatthew G. Knepley 89419ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 89519ad8254SMatthew G. Knepley switch (cs) { 8969371c9d4SSatish Balay case CS_CARTESIAN: 8979371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 8989371c9d4SSatish Balay break; 89919ad8254SMatthew G. Knepley case CS_POLAR: 90063a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 90119ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90219ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90319ad8254SMatthew G. Knepley break; 90419ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 90563a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 90619ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 90719ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 90819ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 90919ad8254SMatthew G. Knepley break; 91019ad8254SMatthew G. Knepley case CS_SPHERICAL: 91163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 91219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 91319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 91419ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 91519ad8254SMatthew G. Knepley break; 91619ad8254SMatthew G. Knepley } 9179566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 91819ad8254SMatthew G. Knepley } 9193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92019ad8254SMatthew G. Knepley } 92119ad8254SMatthew G. Knepley 922d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 923d71ae5a4SJacob Faibussowitsch { 924552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9256858538eSMatthew G. Knepley DM cdm, cdmCell; 9266858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9276858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 928552f7358SJed Brown PetscViewerFormat format; 929552f7358SJed Brown 930552f7358SJed Brown PetscFunctionBegin; 9319566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 932552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 933552f7358SJed Brown const char *name; 934f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9359318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 936552f7358SJed Brown PetscMPIInt rank, size; 937552f7358SJed Brown 9389f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9399f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9409f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9419f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9429f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9439f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9479566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9489566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9509566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 95263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 95363a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 95463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 95663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 957552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 958552f7358SJed Brown PetscInt dof, off, s; 959552f7358SJed Brown 9609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 96248a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 963552f7358SJed Brown } 9649566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 96563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 96663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 967552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 968552f7358SJed Brown PetscInt dof, off, c; 969552f7358SJed Brown 9709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 97248a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c])); 973552f7358SJed Brown } 9749566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9763d2e540fSStefano Zampini if (coordSection && coordinates) { 97719ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9786858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 9796858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 98019ad8254SMatthew G. Knepley PetscMPIInt rank; 98119ad8254SMatthew G. Knepley const char *name; 98219ad8254SMatthew G. Knepley 9839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 9849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 9859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 98663a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 9879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 9886858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 9896858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 9906858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 9916858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 9929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 99363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 99463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 9959566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 99619ad8254SMatthew G. Knepley 9979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 9986858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 9999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 10009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 100119ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 100219ad8254SMatthew G. Knepley PetscInt dof, off; 100319ad8254SMatthew G. Knepley 10046858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10076858538eSMatthew G. Knepley if (dof) { 100863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10099566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 101119ad8254SMatthew G. Knepley } 10126858538eSMatthew G. Knepley } 10136858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10146858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10156858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10166858538eSMatthew G. Knepley if (dof) { 10176858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10186858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10196858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10206858538eSMatthew G. Knepley } 10216858538eSMatthew G. Knepley } 10226858538eSMatthew G. Knepley } 10239566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10249566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10266858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10273d2e540fSStefano Zampini } 10289566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10299566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10309318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10319318fe57SMatthew G. Knepley DMLabel label; 10329318fe57SMatthew G. Knepley PetscBool isdepth; 10339318fe57SMatthew G. Knepley const char *name; 10349318fe57SMatthew G. Knepley 10359566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10379318fe57SMatthew G. Knepley if (isdepth) continue; 10389566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10399566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10409318fe57SMatthew G. Knepley } 1041552f7358SJed Brown if (size > 1) { 1042552f7358SJed Brown PetscSF sf; 1043552f7358SJed Brown 10449566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10459566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1046552f7358SJed Brown } 10474e2e9504SJed Brown if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer)); 10489566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1049552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10500588280cSMatthew G. Knepley const char *name, *color; 10510588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10520588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1053fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1054552f7358SJed Brown PetscReal scale = 2.0; 105578081901SStefano Zampini PetscReal tikzscale = 1.0; 1056b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10570588280cSMatthew G. Knepley double tcoords[3]; 1058552f7358SJed Brown PetscScalar *coords; 1059b7f6ffafSMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n; 1060552f7358SJed Brown PetscMPIInt rank, size; 10610588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1062b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1063fe1cc32dSStefano Zampini PetscBT wp = NULL; 1064fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1065552f7358SJed Brown 10669f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10679f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10689f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10699f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10709f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10719f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10729566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10749566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10750588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10760588280cSMatthew G. Knepley numColors = 10; 10770588280cSMatthew G. Knepley numLColors = 10; 10789566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 10799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 10809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 10819566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1082b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1083b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1084b7f6ffafSMatthew G. Knepley n = 4; 10859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 10861dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 1087*bd3611e6SMatthew G. Knepley n = 4; 10889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 10891dca8a05SBarry Smith PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1); 10909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 10910588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 10929566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 10930588280cSMatthew G. Knepley if (!useColors) { 10940588280cSMatthew G. Knepley numColors = 3; 10959566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 10960588280cSMatthew G. Knepley } 10979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 10980588280cSMatthew G. Knepley if (!useColors) { 10990588280cSMatthew G. Knepley numLColors = 4; 11009566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11010588280cSMatthew G. Knepley } 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1103b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11051dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1106202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1108fe1cc32dSStefano Zampini 1109fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11109566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11129566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11139566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1114fe1cc32dSStefano Zampini if (lflg) { 1115fe1cc32dSStefano Zampini DMLabel lbl; 1116fe1cc32dSStefano Zampini 11179566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1118fe1cc32dSStefano Zampini if (lbl) { 1119fe1cc32dSStefano Zampini PetscInt val, defval; 1120fe1cc32dSStefano Zampini 11219566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11229566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1123fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1124fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1125fe1cc32dSStefano Zampini PetscInt closureSize; 1126fe1cc32dSStefano Zampini 11279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1128fe1cc32dSStefano Zampini if (val == defval) continue; 1129fe1cc32dSStefano Zampini 11309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 113148a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1133fe1cc32dSStefano Zampini } 1134fe1cc32dSStefano Zampini } 1135fe1cc32dSStefano Zampini } 1136fe1cc32dSStefano Zampini 11379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11410588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1142552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1143552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1144552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11455f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11460588280cSMatthew G. Knepley if (size > 1) { 11479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1148770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 114963a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 115063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1151770b213bSMatthew G Knepley } 11529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11530588280cSMatthew G. Knepley } 1154b7f6ffafSMatthew G. Knepley if (drawHasse) { 1155b7f6ffafSMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart)); 1156b7f6ffafSMatthew G. Knepley 115763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 115863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 115963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 116163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 116263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 116463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 116563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 116663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 116763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1169b7f6ffafSMatthew G. Knepley } 11709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1171fe1cc32dSStefano Zampini 1172552f7358SJed Brown /* Plot vertices */ 11739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 11749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1175552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1176552f7358SJed Brown PetscInt off, dof, d; 11770588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1178552f7358SJed Brown 1179fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 11809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 11819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 11829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 118363a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 11840588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 11850588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1186c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 11870588280cSMatthew G. Knepley } 11880588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 11899371c9d4SSatish Balay if (dim == 3) { 11909371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 11919371c9d4SSatish Balay tcoords[1] = tcoords[2]; 11929371c9d4SSatish Balay tcoords[2] = -tmp; 11939371c9d4SSatish Balay } 1194552f7358SJed Brown for (d = 0; d < dof; ++d) { 11959566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 11969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1197552f7358SJed Brown } 1198b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1199b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 12000588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12010588280cSMatthew G. Knepley PetscInt val; 12029566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12039371c9d4SSatish Balay if (val >= 0) { 12049371c9d4SSatish Balay color = lcolors[l % numLColors]; 12059371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12069371c9d4SSatish Balay break; 12079371c9d4SSatish Balay } 12080588280cSMatthew G. Knepley } 1209b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 121063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1211b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 121263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12131baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1214552f7358SJed Brown } 12159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12169566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1217b7f6ffafSMatthew G. Knepley /* Plot edges */ 1218b7f6ffafSMatthew G. Knepley if (plotEdges) { 12199566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1221b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1222b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1223b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1224b7f6ffafSMatthew G. Knepley 1225b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 122763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1233b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1234b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1235b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1236b7f6ffafSMatthew G. Knepley } 1237b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12389371c9d4SSatish Balay if (dim == 3) { 12399371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12409371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12419371c9d4SSatish Balay tcoords[2] = -tmp; 12429371c9d4SSatish Balay } 1243b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12449566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1246b7f6ffafSMatthew G. Knepley } 1247b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1248b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1249b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1250b7f6ffafSMatthew G. Knepley PetscInt val; 1251*bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12529371c9d4SSatish Balay if (val >= 0) { 12539371c9d4SSatish Balay color = lcolors[l % numLColors]; 12549371c9d4SSatish Balay break; 12559371c9d4SSatish Balay } 1256b7f6ffafSMatthew G. Knepley } 125763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1258b7f6ffafSMatthew G. Knepley } 12599566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12609566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1262b7f6ffafSMatthew G. Knepley } 1263846a3e8bSMatthew G. Knepley /* Plot cells */ 1264b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1265846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1266846a3e8bSMatthew G. Knepley const PetscInt *cone; 1267846a3e8bSMatthew G. Knepley 1268fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1269846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1270846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1271846a3e8bSMatthew G. Knepley PetscInt val; 12729566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12739371c9d4SSatish Balay if (val >= 0) { 12749371c9d4SSatish Balay color = lcolors[l % numLColors]; 12759371c9d4SSatish Balay break; 12769371c9d4SSatish Balay } 1277846a3e8bSMatthew G. Knepley } 12789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 127963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1280846a3e8bSMatthew G. Knepley } 1281846a3e8bSMatthew G. Knepley } else { 1282b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1283846a3e8bSMatthew G. Knepley 1284b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1285b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1286fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 12879566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1288c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1289b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1290b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1291b7f6ffafSMatthew G. Knepley 12929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 12939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1294b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1295b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1296b7f6ffafSMatthew G. Knepley 12979566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 129863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank % numColors], econe[0], rank, cone[e], rank, econe[1], rank)); 1299b7f6ffafSMatthew G. Knepley } 1300b7f6ffafSMatthew G. Knepley } else { 1301b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1302b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1303b7f6ffafSMatthew G. Knepley 13049566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1305846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1306846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1307846a3e8bSMatthew G. Knepley 1308b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1309846a3e8bSMatthew G. Knepley } 13109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1311b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1312b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1313b7f6ffafSMatthew G. Knepley 1314b7f6ffafSMatthew G. Knepley if (v > 0) { 1315b7f6ffafSMatthew G. Knepley if (plotEdges) { 1316b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1317b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1318b7f6ffafSMatthew G. Knepley 13199371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13209371c9d4SSatish Balay endpoints[1] = vertex; 13219566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 132263a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 132363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13251baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1326b7f6ffafSMatthew G. Knepley } 132763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1328b7f6ffafSMatthew G. Knepley } 13299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1331846a3e8bSMatthew G. Knepley } 1332846a3e8bSMatthew G. Knepley } 1333b7f6ffafSMatthew G. Knepley } 1334846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1335846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1336846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1337c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1338c713ec31SMatthew G. Knepley const PetscScalar *array; 1339c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1340c713ec31SMatthew G. Knepley PetscBool isDG; 1341846a3e8bSMatthew G. Knepley 1342fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1343c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1344c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1345c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1347c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1348c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1349c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1350846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1351846a3e8bSMatthew G. Knepley } 1352846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13539371c9d4SSatish Balay if (cdim == 3) { 13549371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13559371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13569371c9d4SSatish Balay tcoords[2] = -tmp; 13579371c9d4SSatish Balay } 1358ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1359846a3e8bSMatthew G. Knepley } 1360ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1361c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1362c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13639566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1365846a3e8bSMatthew G. Knepley } 1366b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1367b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1368846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1369846a3e8bSMatthew G. Knepley PetscInt val; 13709566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13719371c9d4SSatish Balay if (val >= 0) { 13729371c9d4SSatish Balay color = lcolors[l % numLColors]; 13739371c9d4SSatish Balay isLabeled = PETSC_TRUE; 13749371c9d4SSatish Balay break; 13759371c9d4SSatish Balay } 1376846a3e8bSMatthew G. Knepley } 1377b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 137863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1379b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 138063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 13811baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1382846a3e8bSMatthew G. Knepley } 1383b7f6ffafSMatthew G. Knepley if (drawHasse) { 1384b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 13859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 13869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 13879566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color)); 13899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1390552f7358SJed Brown 1391b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 13929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 13939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 13949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 13959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color)); 13969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1397b7f6ffafSMatthew G. Knepley 1398b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 13999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 14009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 14019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 14029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color)); 14039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1404b7f6ffafSMatthew G. Knepley 1405b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1406b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1407b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1408b7f6ffafSMatthew G. Knepley 14099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 141148a46eb9SPierre Jolivet for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank)); 14120588280cSMatthew G. Knepley } 14130588280cSMatthew G. Knepley } 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 141763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14189566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14199566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14209566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14219566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14229566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14230f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14240f7d6e4aSStefano Zampini Vec cown, acown; 14250f7d6e4aSStefano Zampini VecScatter sct; 14260f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14270f7d6e4aSStefano Zampini IS gid, acis; 14280f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14290f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14300f7d6e4aSStefano Zampini PetscScalar *array, nid; 14310f7d6e4aSStefano Zampini const PetscInt *idxs; 14320f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14330f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14340f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14350f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14360f7d6e4aSStefano Zampini 14379566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1439b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14410f7d6e4aSStefano Zampini #endif 14420f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14450f7d6e4aSStefano Zampini d1 = 0; 14469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14470f7d6e4aSStefano Zampini nid = d2; 14489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14510f7d6e4aSStefano Zampini } else nid = 0.0; 14520f7d6e4aSStefano Zampini 14530f7d6e4aSStefano Zampini /* Get connectivity */ 14549566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14559566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14560f7d6e4aSStefano Zampini 14570f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14589566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 14620f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 14630f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 14640f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 14650f7d6e4aSStefano Zampini } 14669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 146763a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 14689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14699566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 14700f7d6e4aSStefano Zampini 14710f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 14729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 14739566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 14749566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 14759566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 14760f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 14779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 14789566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 14799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 14819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 14829566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 14839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 14840f7d6e4aSStefano Zampini 14850f7d6e4aSStefano Zampini /* compute edgeCut */ 14860f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 14879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 14889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 14899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 14909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 14919566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 14920f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 14930f7d6e4aSStefano Zampini PetscInt totl; 14940f7d6e4aSStefano Zampini 14950f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 14969566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 14970f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 14980f7d6e4aSStefano Zampini if (work[i] < 0) { 14990f7d6e4aSStefano Zampini ect += 1; 15000f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 15010f7d6e4aSStefano Zampini } 15020f7d6e4aSStefano Zampini } 15030f7d6e4aSStefano Zampini } 15049566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15060f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15070f7d6e4aSStefano Zampini lm[1] = -numVertices; 15081c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 150963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT, -((double)gm[1]) / ((double)gm[0]), -(PetscInt)gm[1], (PetscInt)gm[0])); 15100f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15110f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15120f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15131c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 151463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1515b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 151663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)(gm[1])) / ((double)gm[0]) : 1.)); 15170f7d6e4aSStefano Zampini #else 151863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15190f7d6e4aSStefano Zampini #endif 15209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15219566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15229566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1524552f7358SJed Brown } else { 1525412e9a14SMatthew G. Knepley const char *name; 1526d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1527412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1528d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1529ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15309318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1531412e9a14SMatthew G. Knepley MPI_Comm comm; 1532412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1533552f7358SJed Brown 15349566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15389566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15399566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 154063a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 154163a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 154263a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15452827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1546d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15479566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15489566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1549412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1550412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1551412e9a14SMatthew G. Knepley 15529566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15539566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1554412e9a14SMatthew G. Knepley ict = ct0; 15559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1556412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1557412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1558412e9a14SMatthew G. Knepley DMPolytopeType ct; 1559412e9a14SMatthew G. Knepley 15609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1561412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1562412e9a14SMatthew G. Knepley else ++Nc[1]; 1563412e9a14SMatthew G. Knepley } 1564ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 15659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 15669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 15679566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 156863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1569834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1570dd400576SPatrick Sanan if (rank == 0) { 157163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 157263a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 157363a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1574834065abSMatthew G. Knepley } 1575cbb7f117SMark Adams } 1576ca7bf7eeSMatthew G. Knepley } else { 1577ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1578ca7bf7eeSMatthew G. Knepley 15799371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 15809371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 15819566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 15829371c9d4SSatish Balay locMinMax[0] = Nc[1]; 15839371c9d4SSatish Balay locMinMax[1] = Nc[1]; 15849566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1585ca7bf7eeSMatthew G. Knepley if (d == depth) { 15869371c9d4SSatish Balay locMinMax[0] = gcNum; 15879371c9d4SSatish Balay locMinMax[1] = gcNum; 15889566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1589ca7bf7eeSMatthew G. Knepley } 159063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 15919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 15929566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 15939566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1594ca7bf7eeSMatthew G. Knepley } 15959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1596552f7358SJed Brown } 15979566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 15989318fe57SMatthew G. Knepley { 15999318fe57SMatthew G. Knepley const PetscReal *maxCell; 16009318fe57SMatthew G. Knepley const PetscReal *L; 16016858538eSMatthew G. Knepley PetscBool localized; 16029318fe57SMatthew G. Knepley 16034fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16056858538eSMatthew G. Knepley if (L || localized) { 16066858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16086858538eSMatthew G. Knepley if (L) { 16096858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16109318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16116858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16126858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16139318fe57SMatthew G. Knepley } 16146858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16156858538eSMatthew G. Knepley } 16166858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16189318fe57SMatthew G. Knepley } 16199318fe57SMatthew G. Knepley } 16209566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16219566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1622a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1623a57dd577SMatthew G Knepley DMLabel label; 1624a57dd577SMatthew G Knepley const char *name; 1625a57dd577SMatthew G Knepley IS valueIS; 1626a57dd577SMatthew G Knepley const PetscInt *values; 1627a57dd577SMatthew G Knepley PetscInt numValues, v; 1628a57dd577SMatthew G Knepley 16299566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16319566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 163263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 16339566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 16349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1636a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1637a57dd577SMatthew G Knepley PetscInt size; 1638a57dd577SMatthew G Knepley 16399566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16409566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 164163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1642a57dd577SMatthew G Knepley } 16439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16449566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 16469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1647a57dd577SMatthew G Knepley } 1648c1cad2e7SMatthew G. Knepley { 1649c1cad2e7SMatthew G. Knepley char **labelNames; 1650c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1651c1cad2e7SMatthew G. Knepley PetscBool flg; 1652c1cad2e7SMatthew G. Knepley 16539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 16549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1655c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1656c1cad2e7SMatthew G. Knepley DMLabel label; 1657c1cad2e7SMatthew G. Knepley 16589566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1659c1cad2e7SMatthew G. Knepley if (flg) { 16609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 16619566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1662c1cad2e7SMatthew G. Knepley } 16639566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1664c1cad2e7SMatthew G. Knepley } 16659566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1666c1cad2e7SMatthew G. Knepley } 166734aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 166834aa8a36SMatthew G. Knepley if (dm->Nf) { 166934aa8a36SMatthew G. Knepley PetscInt f; 167034aa8a36SMatthew G. Knepley 167134aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 167234aa8a36SMatthew G. Knepley const char *name; 167334aa8a36SMatthew G. Knepley 16749566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 16759566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 16769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16779566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 167834aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 16799566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 16809566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 168134aa8a36SMatthew G. Knepley } else { 16829566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 16839566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 168434aa8a36SMatthew G. Knepley } 16859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 168634aa8a36SMatthew G. Knepley } 168734aa8a36SMatthew G. Knepley } 16889566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 16898e7ff633SMatthew G. Knepley if (cdm) { 16909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 16919f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 16929566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 16939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 16948e7ff633SMatthew G. Knepley } 1695552f7358SJed Brown } 16963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1697552f7358SJed Brown } 1698552f7358SJed Brown 1699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1700d71ae5a4SJacob Faibussowitsch { 1701e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1702e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1703a12d352dSMatthew G. Knepley PetscInt cdim; 1704e5c487bfSMatthew G. Knepley 1705e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1709e5c487bfSMatthew G. Knepley switch (ct) { 1710a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1711a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1712a12d352dSMatthew G. Knepley switch (cdim) { 17139371c9d4SSatish Balay case 1: { 1714a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1715a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1716a12d352dSMatthew G. Knepley 17179566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17189566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17199566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17209371c9d4SSatish Balay } break; 17219371c9d4SSatish Balay case 2: { 1722a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1723a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1724a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1725a12d352dSMatthew G. Knepley 17269566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17279566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]) + l * dx, PetscRealPart(coords[1]) + l * dy, PetscRealPart(coords[0]) - l * dx, PetscRealPart(coords[1]) - l * dy, PETSC_DRAW_BLACK)); 17289566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]) + l * dx, PetscRealPart(coords[3]) + l * dy, PetscRealPart(coords[2]) - l * dx, PetscRealPart(coords[3]) - l * dy, PETSC_DRAW_BLACK)); 17299371c9d4SSatish Balay } break; 1730d71ae5a4SJacob Faibussowitsch default: 1731d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1732a12d352dSMatthew G. Knepley } 1733a12d352dSMatthew G. Knepley break; 1734e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17359371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17369566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17379566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17389566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1739e5c487bfSMatthew G. Knepley break; 1740e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17419371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17429371c9d4SSatish Balay PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17439566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17449566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17459566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17469566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1747e5c487bfSMatthew G. Knepley break; 17489f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17499f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17509f4ada15SMatthew G. Knepley PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2)); 17519f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17529f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17539f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17549f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 17559f4ada15SMatthew G. Knepley break; 1756d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1757d71ae5a4SJacob Faibussowitsch break; 1758d71ae5a4SJacob Faibussowitsch default: 1759d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1760e5c487bfSMatthew G. Knepley } 17613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1762e5c487bfSMatthew G. Knepley } 1763e5c487bfSMatthew G. Knepley 1764d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1765d71ae5a4SJacob Faibussowitsch { 1766e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1767e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1768e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1769e5c487bfSMatthew G. Knepley PetscInt fillColor, v, e, d; 1770e5c487bfSMatthew G. Knepley 1771e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17739566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1774e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1775e5c487bfSMatthew G. Knepley switch (ct) { 17769371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 1777e5c487bfSMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1778e5c487bfSMatthew G. Knepley 17799371c9d4SSatish Balay for (v = 0; v < 3; ++v) { 17809371c9d4SSatish Balay centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.; 17819371c9d4SSatish Balay centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.; 17829371c9d4SSatish Balay } 1783e5c487bfSMatthew G. Knepley for (e = 0; e < 3; ++e) { 1784e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1785e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1786e5c487bfSMatthew G. Knepley for (d = 1; d <= edgeDiv; ++d) { 1787e5c487bfSMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv; 1788e5c487bfSMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv; 1789e5c487bfSMatthew G. Knepley } 17909566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1791e5c487bfSMatthew G. Knepley for (d = 0; d < edgeDiv; ++d) { 17929566063dSJacob 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)); 17939566063dSJacob 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)); 1794e5c487bfSMatthew G. Knepley } 1795e5c487bfSMatthew G. Knepley } 17969371c9d4SSatish Balay } break; 1797d71ae5a4SJacob Faibussowitsch default: 1798d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1799e5c487bfSMatthew G. Knepley } 18003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1801e5c487bfSMatthew G. Knepley } 1802e5c487bfSMatthew G. Knepley 1803d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1804d71ae5a4SJacob Faibussowitsch { 1805e412dcbdSMatthew G. Knepley PetscDraw draw; 1806e412dcbdSMatthew G. Knepley DM cdm; 1807e412dcbdSMatthew G. Knepley PetscSection coordSection; 1808e412dcbdSMatthew G. Knepley Vec coordinates; 1809c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1810e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1811e5c487bfSMatthew G. Knepley PetscBool isnull, drawAffine = PETSC_TRUE; 1812c9c77995SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4; 1813e412dcbdSMatthew G. Knepley 1814e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 181663a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 18179566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18189566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18209566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18229566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18239566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1824e412dcbdSMatthew G. Knepley 18259566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18269566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18273ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18289566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1829e412dcbdSMatthew G. Knepley 1830c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18319566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18329566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1833e412dcbdSMatthew G. Knepley 1834cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1835cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1836c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1837ba2698f1SMatthew G. Knepley PetscInt numCoords; 1838c9c77995SMatthew G. Knepley PetscBool isDG; 1839cf3064d3SMatthew G. Knepley 1840c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 18411baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 18421baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1843c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1844cf3064d3SMatthew G. Knepley } 18459566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 18469566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 18479566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 18489566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 18493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1850e412dcbdSMatthew G. Knepley } 1851e412dcbdSMatthew G. Knepley 1852e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1853e44f6aebSMatthew G. Knepley { 1854e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1855e44f6aebSMatthew G. Knepley PetscFE fe; 1856e44f6aebSMatthew G. Knepley PetscSpace sp; 1857e44f6aebSMatthew G. Knepley PetscClassId id; 1858e44f6aebSMatthew G. Knepley PetscInt degree; 1859e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1860e44f6aebSMatthew G. Knepley 1861e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1862e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1863e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1864e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1865e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1866e44f6aebSMatthew G. Knepley *hdm = dm; 1867e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1868e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1869e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1870e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1871e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1872e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1873e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1874e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1875e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1876e44f6aebSMatthew G. Knepley Mat In; 1877e44f6aebSMatthew G. Knepley Vec cl, rcl; 1878e44f6aebSMatthew G. Knepley 1879e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1880e44f6aebSMatthew G. Knepley if (rd > 1) PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1881e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1882e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1883e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1884e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1885e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1886e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1887e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1888e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1889e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1890e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1891e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1892e44f6aebSMatthew G. Knepley odm = rdm; 1893e44f6aebSMatthew G. Knepley } 1894e44f6aebSMatthew G. Knepley *hdm = rdm; 1895e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1896e44f6aebSMatthew G. Knepley } 1897e44f6aebSMatthew G. Knepley 18981e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 18991e50132fSMatthew G. Knepley #include <exodusII.h> 19006823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19011e50132fSMatthew G. Knepley #endif 19021e50132fSMatthew G. Knepley 1903d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1904d71ae5a4SJacob Faibussowitsch { 19055f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1906002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1907552f7358SJed Brown 1908552f7358SJed Brown PetscFunctionBegin; 1909552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1910552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19175f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1918552f7358SJed Brown if (iascii) { 19198135c375SStefano Zampini PetscViewerFormat format; 19209566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19211baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19221baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1923c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1924c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19259566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1926c6ccd67eSMatthew G. Knepley #else 1927c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1928552f7358SJed Brown #endif 1929e412dcbdSMatthew G. Knepley } else if (isvtk) { 19309566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1931e412dcbdSMatthew G. Knepley } else if (isdraw) { 1932e44f6aebSMatthew G. Knepley DM hdm; 1933e44f6aebSMatthew G. Knepley 1934e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1935e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1936e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 19378135c375SStefano Zampini } else if (isglvis) { 19389566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 19391e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19401e50132fSMatthew G. Knepley } else if (isexodus) { 19416823f3c5SBlaise Bourdin /* 19426823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 19436823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 1944da81f932SPierre Jolivet with ID 1, containing all cells. 19456823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 19466823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 19476823f3c5SBlaise Bourdin */ 19486823f3c5SBlaise Bourdin PetscInt numCS; 19499566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 19506823f3c5SBlaise Bourdin if (!numCS) { 19511e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 19529566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 19539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 19549566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 19556823f3c5SBlaise Bourdin } 19569566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 19571e50132fSMatthew G. Knepley #endif 19585f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 19595f34f2dcSJed Brown } else if (iscgns) { 19605f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 19615f34f2dcSJed Brown #endif 19621baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 1963cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 19649566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 1965cb3ba0daSMatthew G. Knepley if (flg) { 1966cb3ba0daSMatthew G. Knepley Vec ranks; 19679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 19689566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 19699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 1970cb3ba0daSMatthew G. Knepley } 1971002a2709SMatthew G. Knepley /* Optionally view a label */ 19729566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 1973002a2709SMatthew G. Knepley if (flg) { 1974002a2709SMatthew G. Knepley DMLabel label; 1975002a2709SMatthew G. Knepley Vec val; 1976002a2709SMatthew G. Knepley 19779566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 197828b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 19799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 19809566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 19819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 1982002a2709SMatthew G. Knepley } 19833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1984552f7358SJed Brown } 1985552f7358SJed Brown 19867f96f51bSksagiyam /*@ 1987a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 19887f96f51bSksagiyam 198920f4b53cSBarry Smith Collective 19907f96f51bSksagiyam 19917f96f51bSksagiyam Input Parameters: 1992a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 1993a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 19947f96f51bSksagiyam 19957f96f51bSksagiyam Level: advanced 19967f96f51bSksagiyam 19971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 19987f96f51bSksagiyam @*/ 1999d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2000d71ae5a4SJacob Faibussowitsch { 20017f96f51bSksagiyam PetscBool ishdf5; 20027f96f51bSksagiyam 20037f96f51bSksagiyam PetscFunctionBegin; 20047f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20057f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20087f96f51bSksagiyam if (ishdf5) { 20097f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20107f96f51bSksagiyam PetscViewerFormat format; 20119566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20127f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20137f96f51bSksagiyam IS globalPointNumbering; 20147f96f51bSksagiyam 20159566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20169566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 201898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20197f96f51bSksagiyam #else 20207f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20217f96f51bSksagiyam #endif 20227f96f51bSksagiyam } 20239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20257f96f51bSksagiyam } 20267f96f51bSksagiyam 202777b8e257Sksagiyam /*@ 2028a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 202977b8e257Sksagiyam 203020f4b53cSBarry Smith Collective 203177b8e257Sksagiyam 203277b8e257Sksagiyam Input Parameters: 2033a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2034a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 203577b8e257Sksagiyam 203677b8e257Sksagiyam Level: advanced 203777b8e257Sksagiyam 20381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 203977b8e257Sksagiyam @*/ 2040d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2041d71ae5a4SJacob Faibussowitsch { 204277b8e257Sksagiyam PetscBool ishdf5; 204377b8e257Sksagiyam 204477b8e257Sksagiyam PetscFunctionBegin; 204577b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 204677b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 204977b8e257Sksagiyam if (ishdf5) { 205077b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 205177b8e257Sksagiyam PetscViewerFormat format; 20529566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 205377b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20549566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2055fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 205677b8e257Sksagiyam #else 205777b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 205877b8e257Sksagiyam #endif 205977b8e257Sksagiyam } 20609566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 20613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 206277b8e257Sksagiyam } 206377b8e257Sksagiyam 2064bd6565f1Sksagiyam /*@ 2065a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2066bd6565f1Sksagiyam 206720f4b53cSBarry Smith Collective 2068bd6565f1Sksagiyam 2069bd6565f1Sksagiyam Input Parameters: 2070a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2071a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2072bd6565f1Sksagiyam 2073bd6565f1Sksagiyam Level: advanced 2074bd6565f1Sksagiyam 20751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2076bd6565f1Sksagiyam @*/ 2077d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2078d71ae5a4SJacob Faibussowitsch { 2079bd6565f1Sksagiyam PetscBool ishdf5; 2080bd6565f1Sksagiyam 2081bd6565f1Sksagiyam PetscFunctionBegin; 2082bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2083bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2086bd6565f1Sksagiyam if (ishdf5) { 2087bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2088bd6565f1Sksagiyam IS globalPointNumbering; 2089bd6565f1Sksagiyam PetscViewerFormat format; 2090bd6565f1Sksagiyam 20919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2092bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20939566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20949566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 209698921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2097bd6565f1Sksagiyam #else 2098bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2099bd6565f1Sksagiyam #endif 2100bd6565f1Sksagiyam } 21019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2103bd6565f1Sksagiyam } 2104bd6565f1Sksagiyam 2105021affd3Sksagiyam /*@ 2106a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2107021affd3Sksagiyam 210820f4b53cSBarry Smith Collective 2109021affd3Sksagiyam 2110021affd3Sksagiyam Input Parameters: 2111a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2112a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 2113a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved 2114021affd3Sksagiyam 2115021affd3Sksagiyam Level: advanced 2116021affd3Sksagiyam 2117021affd3Sksagiyam Notes: 2118420bcc1bSBarry 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. 2119021affd3Sksagiyam 2120420bcc1bSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2121021affd3Sksagiyam 21221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2123021affd3Sksagiyam @*/ 2124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2125d71ae5a4SJacob Faibussowitsch { 2126021affd3Sksagiyam PetscBool ishdf5; 2127021affd3Sksagiyam 2128021affd3Sksagiyam PetscFunctionBegin; 2129021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2130021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2131021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21329566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2134021affd3Sksagiyam if (ishdf5) { 2135021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 21369566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2137021affd3Sksagiyam #else 2138021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2139021affd3Sksagiyam #endif 2140021affd3Sksagiyam } 21419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 21423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2143021affd3Sksagiyam } 2144021affd3Sksagiyam 21453e97647fSksagiyam /*@ 21463e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 21473e97647fSksagiyam 214820f4b53cSBarry Smith Collective 21493e97647fSksagiyam 21503e97647fSksagiyam Input Parameters: 2151a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2152a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 2153a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 21543e97647fSksagiyam - vec - The global vector to be saved 21553e97647fSksagiyam 21563e97647fSksagiyam Level: advanced 21573e97647fSksagiyam 21583e97647fSksagiyam Notes: 2159420bcc1bSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 21603e97647fSksagiyam 216160225df5SJacob Faibussowitsch Calling sequence: 2162a1cb98faSBarry Smith .vb 2163a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2164a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2165a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2166a1cb98faSBarry Smith DMClone(dm, §iondm); 2167a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2168a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2169a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2170a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2171a1cb98faSBarry Smith PetscSectionSetUp(section); 2172a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2173a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2174a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2175a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2176a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2177a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2178a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2179a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2180a1cb98faSBarry Smith DMDestroy(§iondm); 2181a1cb98faSBarry Smith DMDestroy(&dm); 2182a1cb98faSBarry Smith .ve 21833e97647fSksagiyam 21841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 21853e97647fSksagiyam @*/ 2186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2187d71ae5a4SJacob Faibussowitsch { 21883e97647fSksagiyam PetscBool ishdf5; 21893e97647fSksagiyam 21903e97647fSksagiyam PetscFunctionBegin; 21913e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 21923e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21933e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21943e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 21953e97647fSksagiyam /* Check consistency */ 21963e97647fSksagiyam { 21973e97647fSksagiyam PetscSection section; 21983e97647fSksagiyam PetscBool includesConstraints; 21993e97647fSksagiyam PetscInt m, m1; 22003e97647fSksagiyam 22019566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22029566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22049566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22059566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 220663a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22073e97647fSksagiyam } 22089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22103e97647fSksagiyam if (ishdf5) { 22113e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22129566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22133e97647fSksagiyam #else 22143e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22153e97647fSksagiyam #endif 22163e97647fSksagiyam } 22179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22193e97647fSksagiyam } 22203e97647fSksagiyam 22213e97647fSksagiyam /*@ 22223e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22233e97647fSksagiyam 222420f4b53cSBarry Smith Collective 22253e97647fSksagiyam 22263e97647fSksagiyam Input Parameters: 2227a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2228a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 222920f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm` 22303e97647fSksagiyam - vec - The local vector to be saved 22313e97647fSksagiyam 22323e97647fSksagiyam Level: advanced 22333e97647fSksagiyam 2234a1cb98faSBarry Smith Note: 223520f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 22363e97647fSksagiyam 223760225df5SJacob Faibussowitsch Calling sequence: 2238a1cb98faSBarry Smith .vb 2239a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2240a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2241a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2242a1cb98faSBarry Smith DMClone(dm, §iondm); 2243a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2244a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2245a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2246a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2247a1cb98faSBarry Smith PetscSectionSetUp(section); 2248a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2249a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2250a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2251a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2252a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2253a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2254a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2255a1cb98faSBarry Smith DMDestroy(§iondm); 2256a1cb98faSBarry Smith DMDestroy(&dm); 2257a1cb98faSBarry Smith .ve 22583e97647fSksagiyam 22591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22603e97647fSksagiyam @*/ 2261d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2262d71ae5a4SJacob Faibussowitsch { 22633e97647fSksagiyam PetscBool ishdf5; 22643e97647fSksagiyam 22653e97647fSksagiyam PetscFunctionBegin; 22663e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22673e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22683e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22693e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22703e97647fSksagiyam /* Check consistency */ 22713e97647fSksagiyam { 22723e97647fSksagiyam PetscSection section; 22733e97647fSksagiyam PetscBool includesConstraints; 22743e97647fSksagiyam PetscInt m, m1; 22753e97647fSksagiyam 22769566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 22789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22799566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22809566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 228163a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 22823e97647fSksagiyam } 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 22853e97647fSksagiyam if (ishdf5) { 22863e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22879566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22883e97647fSksagiyam #else 22893e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22903e97647fSksagiyam #endif 22913e97647fSksagiyam } 22929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 22933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22943e97647fSksagiyam } 22953e97647fSksagiyam 2296d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2297d71ae5a4SJacob Faibussowitsch { 2298d4f5a9a0SVaclav Hapla PetscBool ishdf5; 22992c40f234SMatthew G. Knepley 23002c40f234SMatthew G. Knepley PetscFunctionBegin; 23012c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23022c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2304d4f5a9a0SVaclav Hapla if (ishdf5) { 23052c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23069c48423bSVaclav Hapla PetscViewerFormat format; 23079566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23089c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23099566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2310509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23119566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 231298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23142c40f234SMatthew G. Knepley #else 23152c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2316552f7358SJed Brown #endif 231798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2318552f7358SJed Brown } 2319552f7358SJed Brown 2320ea8e1828Sksagiyam /*@ 2321a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2322ea8e1828Sksagiyam 232320f4b53cSBarry Smith Collective 2324ea8e1828Sksagiyam 2325ea8e1828Sksagiyam Input Parameters: 2326a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2327a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2328ea8e1828Sksagiyam 23292fe279fdSBarry Smith Output Parameter: 233020f4b53cSBarry 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 2331dec9e869Sksagiyam 2332ea8e1828Sksagiyam Level: advanced 2333ea8e1828Sksagiyam 23341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2335a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2336ea8e1828Sksagiyam @*/ 2337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2338d71ae5a4SJacob Faibussowitsch { 2339ea8e1828Sksagiyam PetscBool ishdf5; 2340ea8e1828Sksagiyam 2341ea8e1828Sksagiyam PetscFunctionBegin; 2342ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2343ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23444f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 23459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23469566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2347ea8e1828Sksagiyam if (ishdf5) { 2348ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2349ea8e1828Sksagiyam PetscViewerFormat format; 23509566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2351ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23529566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 235398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2354ea8e1828Sksagiyam #else 2355ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2356ea8e1828Sksagiyam #endif 2357ea8e1828Sksagiyam } 23589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 23593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2360ea8e1828Sksagiyam } 2361ea8e1828Sksagiyam 23623e701f1cSksagiyam /*@ 2363a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 23643e701f1cSksagiyam 236520f4b53cSBarry Smith Collective 23663e701f1cSksagiyam 23673e701f1cSksagiyam Input Parameters: 2368a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2369a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2370a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 23713e701f1cSksagiyam 23723e701f1cSksagiyam Level: advanced 23733e701f1cSksagiyam 23741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2375a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 23763e701f1cSksagiyam @*/ 2377d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2378d71ae5a4SJacob Faibussowitsch { 23793e701f1cSksagiyam PetscBool ishdf5; 23803e701f1cSksagiyam 23813e701f1cSksagiyam PetscFunctionBegin; 23823e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23833e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2384c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 23859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 23873e701f1cSksagiyam if (ishdf5) { 23883e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 23893e701f1cSksagiyam PetscViewerFormat format; 23909566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23913e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23929566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 239398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23943e701f1cSksagiyam #else 23953e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23963e701f1cSksagiyam #endif 23973e701f1cSksagiyam } 23989566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 23993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24003e701f1cSksagiyam } 24013e701f1cSksagiyam 2402b08ad5deSksagiyam /*@ 2403a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2404b08ad5deSksagiyam 240520f4b53cSBarry Smith Collective 2406b08ad5deSksagiyam 2407b08ad5deSksagiyam Input Parameters: 2408a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2409a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 241020f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2411b08ad5deSksagiyam 2412b08ad5deSksagiyam Level: advanced 2413b08ad5deSksagiyam 2414a1cb98faSBarry Smith Note: 2415a1cb98faSBarry Smith The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs. 2416e6368b79SVaclav Hapla 24171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2418a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2419b08ad5deSksagiyam @*/ 2420d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2421d71ae5a4SJacob Faibussowitsch { 2422b08ad5deSksagiyam PetscBool ishdf5; 2423b08ad5deSksagiyam 2424b08ad5deSksagiyam PetscFunctionBegin; 2425b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2426b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2427e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2430b08ad5deSksagiyam if (ishdf5) { 2431b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2432b08ad5deSksagiyam PetscViewerFormat format; 2433b08ad5deSksagiyam 24349566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2435b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24369566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 243798921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2438b08ad5deSksagiyam #else 2439b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2440b08ad5deSksagiyam #endif 2441b08ad5deSksagiyam } 24429566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 24433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2444b08ad5deSksagiyam } 2445b08ad5deSksagiyam 2446f84dd6b4Sksagiyam /*@ 2447a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2448f84dd6b4Sksagiyam 244920f4b53cSBarry Smith Collective 2450f84dd6b4Sksagiyam 2451f84dd6b4Sksagiyam Input Parameters: 2452a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2453a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 2454a1cb98faSBarry Smith . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated 2455a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2456f84dd6b4Sksagiyam 2457a4e35b19SJacob Faibussowitsch Output Parameters: 245820f4b53cSBarry 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) 245920f4b53cSBarry 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) 2460f84dd6b4Sksagiyam 2461f84dd6b4Sksagiyam Level: advanced 2462f84dd6b4Sksagiyam 2463f84dd6b4Sksagiyam Notes: 246420f4b53cSBarry 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. 2465f84dd6b4Sksagiyam 246620f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2467f84dd6b4Sksagiyam 246820f4b53cSBarry 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. 2469f84dd6b4Sksagiyam 2470f84dd6b4Sksagiyam Example using 2 processes: 2471a1cb98faSBarry Smith .vb 2472a1cb98faSBarry Smith NX (number of points on dm): 4 2473a1cb98faSBarry Smith sectionA : the on-disk section 2474a1cb98faSBarry Smith vecA : a vector associated with sectionA 2475a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2476a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2477a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2478f84dd6b4Sksagiyam 2479a1cb98faSBarry Smith rank 0 rank 1 2480a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2481a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2482a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2483a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2484a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2485a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2486a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2487a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2488a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2489a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2490a1cb98faSBarry Smith .ve 2491a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2492a1cb98faSBarry Smith 24931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2494f84dd6b4Sksagiyam @*/ 2495d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2496d71ae5a4SJacob Faibussowitsch { 2497f84dd6b4Sksagiyam PetscBool ishdf5; 2498f84dd6b4Sksagiyam 2499f84dd6b4Sksagiyam PetscFunctionBegin; 2500f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2501f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2502f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2503f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25044f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25054f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2508f84dd6b4Sksagiyam if (ishdf5) { 2509f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25109566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2511f84dd6b4Sksagiyam #else 2512f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2513f84dd6b4Sksagiyam #endif 2514f84dd6b4Sksagiyam } 25159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2517f84dd6b4Sksagiyam } 2518f84dd6b4Sksagiyam 25198be3dfe1Sksagiyam /*@ 25208be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25218be3dfe1Sksagiyam 252220f4b53cSBarry Smith Collective 25238be3dfe1Sksagiyam 25248be3dfe1Sksagiyam Input Parameters: 2525a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2526a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2527a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined 2528a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25298be3dfe1Sksagiyam - vec - The global vector to set values of 25308be3dfe1Sksagiyam 25318be3dfe1Sksagiyam Level: advanced 25328be3dfe1Sksagiyam 25338be3dfe1Sksagiyam Notes: 2534a1cb98faSBarry Smith In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 25358be3dfe1Sksagiyam 253660225df5SJacob Faibussowitsch Calling sequence: 2537a1cb98faSBarry Smith .vb 2538a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2539a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2540a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2541a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2542a1cb98faSBarry Smith DMClone(dm, §iondm); 2543a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2544a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2545a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2546a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2547a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2548a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2549a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2550a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2551a1cb98faSBarry Smith DMDestroy(§iondm); 2552a1cb98faSBarry Smith DMDestroy(&dm); 2553a1cb98faSBarry Smith .ve 25548be3dfe1Sksagiyam 25551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2556a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 25578be3dfe1Sksagiyam @*/ 2558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2559d71ae5a4SJacob Faibussowitsch { 25608be3dfe1Sksagiyam PetscBool ishdf5; 25618be3dfe1Sksagiyam 25628be3dfe1Sksagiyam PetscFunctionBegin; 25638be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25648be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25658be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 25668be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 25678be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 25688be3dfe1Sksagiyam /* Check consistency */ 25698be3dfe1Sksagiyam { 25708be3dfe1Sksagiyam PetscSection section; 25718be3dfe1Sksagiyam PetscBool includesConstraints; 25728be3dfe1Sksagiyam PetscInt m, m1; 25738be3dfe1Sksagiyam 25749566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 25759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 25769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 25779566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 25789566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 257963a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 25808be3dfe1Sksagiyam } 25819566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25829566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 25838be3dfe1Sksagiyam if (ishdf5) { 25848be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 25859566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 25868be3dfe1Sksagiyam #else 25878be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 25888be3dfe1Sksagiyam #endif 25898be3dfe1Sksagiyam } 25909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 25913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25928be3dfe1Sksagiyam } 25938be3dfe1Sksagiyam 25948be3dfe1Sksagiyam /*@ 25958be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 25968be3dfe1Sksagiyam 259720f4b53cSBarry Smith Collective 25988be3dfe1Sksagiyam 25998be3dfe1Sksagiyam Input Parameters: 2600a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2601a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 2602a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined 2603a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26048be3dfe1Sksagiyam - vec - The local vector to set values of 26058be3dfe1Sksagiyam 26068be3dfe1Sksagiyam Level: advanced 26078be3dfe1Sksagiyam 26088be3dfe1Sksagiyam Notes: 260920f4b53cSBarry Smith In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 26108be3dfe1Sksagiyam 261160225df5SJacob Faibussowitsch Calling sequence: 2612a1cb98faSBarry Smith .vb 2613a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2614a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2615a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2616a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2617a1cb98faSBarry Smith DMClone(dm, §iondm); 2618a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2619a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2620a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2621a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2622a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2623a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2624a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2625a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2626a1cb98faSBarry Smith DMDestroy(§iondm); 2627a1cb98faSBarry Smith DMDestroy(&dm); 2628a1cb98faSBarry Smith .ve 26298be3dfe1Sksagiyam 26301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2631a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26328be3dfe1Sksagiyam @*/ 2633d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2634d71ae5a4SJacob Faibussowitsch { 26358be3dfe1Sksagiyam PetscBool ishdf5; 26368be3dfe1Sksagiyam 26378be3dfe1Sksagiyam PetscFunctionBegin; 26388be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26398be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26408be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26418be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26428be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26438be3dfe1Sksagiyam /* Check consistency */ 26448be3dfe1Sksagiyam { 26458be3dfe1Sksagiyam PetscSection section; 26468be3dfe1Sksagiyam PetscBool includesConstraints; 26478be3dfe1Sksagiyam PetscInt m, m1; 26488be3dfe1Sksagiyam 26499566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26509566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 26519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26529566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26539566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 265463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 26558be3dfe1Sksagiyam } 26569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26588be3dfe1Sksagiyam if (ishdf5) { 26598be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26609566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26618be3dfe1Sksagiyam #else 26628be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26638be3dfe1Sksagiyam #endif 26648be3dfe1Sksagiyam } 26659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 26663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26678be3dfe1Sksagiyam } 26688be3dfe1Sksagiyam 2669d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2670d71ae5a4SJacob Faibussowitsch { 2671552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2672552f7358SJed Brown 2673552f7358SJed Brown PetscFunctionBegin; 26749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 26759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 26769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 26779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 26786c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 26792e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 26802e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 26812e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 26822e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 26836bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 26846bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2685c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2686c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2687d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2688d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 26895f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 26903ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 26919566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 26929566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 26939566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 26949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 26959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 26969566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 269721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 26989f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 26999566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27009566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27019566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27021d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27049566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27084e2e9504SJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.face_sf)); 27096725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 27106725e60dSJed Brown PetscCall(ISDestroy(&mesh->periodic.periodic_points)); 27119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27139566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27149566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27159566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27169566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27179566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27189566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 27199566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 27209566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 27219566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2722552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 27239566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 27243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2725552f7358SJed Brown } 2726552f7358SJed Brown 2727d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2728d71ae5a4SJacob Faibussowitsch { 27298d1174e4SMatthew G. Knepley PetscSection sectionGlobal; 2730acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 27319fca9976SJed Brown PetscInt localSize, localStart = 0; 2732837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2733b412c318SBarry Smith MatType mtype; 27341428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2735552f7358SJed Brown 2736552f7358SJed Brown PetscFunctionBegin; 27379566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2738b412c318SBarry Smith mtype = dm->mattype; 27399566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 27409566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 27419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 27429fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 27439566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 27449566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 27459566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 27469566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 27479566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2748acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 27499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 27509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 27519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 27529566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 27539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 27549566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 27559566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 27569566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2757552f7358SJed Brown if (!isShell) { 2758837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 27599fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 2760863027abSJed Brown PetscInt pStart, pEnd, p, dof, cdof, num_fields; 2761552f7358SJed Brown 27629566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 27639fca9976SJed Brown 27649fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 27659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2766863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 2767e432b41dSStefano Zampini for (p = pStart; p < pEnd; ++p) { 2768863027abSJed Brown switch (dm->blocking_type) { 27690e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 27709fca9976SJed Brown PetscInt bdof, offset; 2771a9d99c84SMatthew G. Knepley 27729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 27739fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 27749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 27759371c9d4SSatish Balay for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof; 27761d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 27771d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 27781d17a0a3SMatthew G. Knepley if (dof) { 27799371c9d4SSatish Balay if (bs < 0) { 27809371c9d4SSatish Balay bs = bdof; 27819371c9d4SSatish Balay } else if (bs != bdof) { 27829371c9d4SSatish Balay bs = 1; 27839371c9d4SSatish Balay } 2784552f7358SJed Brown } 2785863027abSJed Brown } break; 2786863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2787863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2788863027abSJed Brown PetscInt num_comp, bdof, offset; 2789863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2790863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2791863027abSJed Brown if (dof < 0) continue; 2792863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2793863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2794863027abSJed 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); 2795863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2796863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2797863027abSJed Brown // Handle possibly constant block size (unlikely) 2798863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2799863027abSJed Brown if (dof) { 2800863027abSJed Brown if (bs < 0) { 2801863027abSJed Brown bs = bdof; 2802863027abSJed Brown } else if (bs != bdof) { 2803863027abSJed Brown bs = 1; 2804863027abSJed Brown } 2805863027abSJed Brown } 2806863027abSJed Brown } 2807863027abSJed Brown } break; 2808863027abSJed Brown } 28092a28c762SMatthew G Knepley } 28102a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2811e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2812e432b41dSStefano Zampini bsLocal[1] = bs; 28139566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2814e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2815e432b41dSStefano Zampini else bs = bsMinMax[0]; 28166fd5c86aSStefano Zampini bs = PetscMax(1, bs); 28179566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 28180682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 28199566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 28209566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 28210682b8bbSJed Brown } else { 28229566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 28239566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 28249566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2825552f7358SJed Brown } 28269fca9976SJed Brown { // Consolidate blocks 28279fca9976SJed Brown PetscInt nblocks = 0; 28289fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 28299fca9976SJed Brown if (pblocks[i] == 0) continue; 28309fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2831ad540459SPierre 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]); 28329fca9976SJed Brown } 28339fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 28349fca9976SJed Brown } 28359fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2836aa0f6e3cSJed Brown } 28379566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 28383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2839552f7358SJed Brown } 2840552f7358SJed Brown 28417cd05799SMatthew G. Knepley /*@ 2842a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2843be36d101SStefano Zampini 2844a1cb98faSBarry Smith Not Collective 2845be36d101SStefano Zampini 2846be36d101SStefano Zampini Input Parameter: 284760225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2848be36d101SStefano Zampini 28492fe279fdSBarry Smith Output Parameter: 2850be36d101SStefano Zampini . subsection - The subdomain section 2851be36d101SStefano Zampini 2852be36d101SStefano Zampini Level: developer 2853be36d101SStefano Zampini 28541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 28557cd05799SMatthew G. Knepley @*/ 2856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2857d71ae5a4SJacob Faibussowitsch { 2858be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2859be36d101SStefano Zampini 2860be36d101SStefano Zampini PetscFunctionBegin; 2861be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2862be36d101SStefano Zampini if (!mesh->subdomainSection) { 2863be36d101SStefano Zampini PetscSection section; 2864be36d101SStefano Zampini PetscSF sf; 2865be36d101SStefano Zampini 28669566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 28679566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 28689566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 28699566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2870be36d101SStefano Zampini } 2871be36d101SStefano Zampini *subsection = mesh->subdomainSection; 28723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2873be36d101SStefano Zampini } 2874be36d101SStefano Zampini 2875552f7358SJed Brown /*@ 287620f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2877552f7358SJed Brown 2878a1cb98faSBarry Smith Not Collective 2879552f7358SJed Brown 2880552f7358SJed Brown Input Parameter: 288160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2882552f7358SJed Brown 2883552f7358SJed Brown Output Parameters: 2884552f7358SJed Brown + pStart - The first mesh point 2885552f7358SJed Brown - pEnd - The upper bound for mesh points 2886552f7358SJed Brown 2887552f7358SJed Brown Level: beginner 2888552f7358SJed Brown 28891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 2890552f7358SJed Brown @*/ 2891d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 2892d71ae5a4SJacob Faibussowitsch { 2893552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2894552f7358SJed Brown 2895552f7358SJed Brown PetscFunctionBegin; 2896552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28979f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 28989f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 28993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2900552f7358SJed Brown } 2901552f7358SJed Brown 2902552f7358SJed Brown /*@ 290320f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 2904552f7358SJed Brown 2905a1cb98faSBarry Smith Not Collective 2906552f7358SJed Brown 2907552f7358SJed Brown Input Parameters: 290860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2909552f7358SJed Brown . pStart - The first mesh point 2910552f7358SJed Brown - pEnd - The upper bound for mesh points 2911552f7358SJed Brown 2912552f7358SJed Brown Level: beginner 2913552f7358SJed Brown 29141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 2915552f7358SJed Brown @*/ 2916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 2917d71ae5a4SJacob Faibussowitsch { 2918552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2919552f7358SJed Brown 2920552f7358SJed Brown PetscFunctionBegin; 2921552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 29239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 292421027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 29253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2926552f7358SJed Brown } 2927552f7358SJed Brown 2928552f7358SJed Brown /*@ 2929eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 2930552f7358SJed Brown 2931a1cb98faSBarry Smith Not Collective 2932552f7358SJed Brown 2933552f7358SJed Brown Input Parameters: 293460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2935a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2936552f7358SJed Brown 2937552f7358SJed Brown Output Parameter: 293820f4b53cSBarry Smith . size - The cone size for point `p` 2939552f7358SJed Brown 2940552f7358SJed Brown Level: beginner 2941552f7358SJed Brown 29421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 2943552f7358SJed Brown @*/ 2944d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 2945d71ae5a4SJacob Faibussowitsch { 2946552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2947552f7358SJed Brown 2948552f7358SJed Brown PetscFunctionBegin; 2949552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29504f572ea9SToby Isaac PetscAssertPointer(size, 3); 29519f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 29529f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 29533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2954552f7358SJed Brown } 2955552f7358SJed Brown 2956552f7358SJed Brown /*@ 2957eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 2958552f7358SJed Brown 2959a1cb98faSBarry Smith Not Collective 2960552f7358SJed Brown 2961552f7358SJed Brown Input Parameters: 296260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 2963a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 296420f4b53cSBarry Smith - size - The cone size for point `p` 2965552f7358SJed Brown 2966552f7358SJed Brown Level: beginner 2967552f7358SJed Brown 2968a1cb98faSBarry Smith Note: 2969a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 2970a1cb98faSBarry Smith 29711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 2972552f7358SJed Brown @*/ 2973d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 2974d71ae5a4SJacob Faibussowitsch { 2975552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2976552f7358SJed Brown 2977552f7358SJed Brown PetscFunctionBegin; 2978552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 29799f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 29809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 29813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2982552f7358SJed Brown } 2983552f7358SJed Brown 2984552f7358SJed Brown /*@C 2985eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 2986552f7358SJed Brown 2987a1cb98faSBarry Smith Not Collective 2988552f7358SJed Brown 2989552f7358SJed Brown Input Parameters: 2990a1cb98faSBarry Smith + dm - The `DMPLEX` 2991a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 2992552f7358SJed Brown 2993552f7358SJed Brown Output Parameter: 299420f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p` 2995552f7358SJed Brown 2996552f7358SJed Brown Level: beginner 2997552f7358SJed Brown 299860225df5SJacob Faibussowitsch Fortran Notes: 2999a1cb98faSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 3000a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 30013813dfbdSMatthew G Knepley 30021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3003552f7358SJed Brown @*/ 3004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3005d71ae5a4SJacob Faibussowitsch { 3006552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3007552f7358SJed Brown PetscInt off; 3008552f7358SJed Brown 3009552f7358SJed Brown PetscFunctionBegin; 3010552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30114f572ea9SToby Isaac PetscAssertPointer(cone, 3); 30129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3013552f7358SJed Brown *cone = &mesh->cones[off]; 30143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3015552f7358SJed Brown } 3016552f7358SJed Brown 30170ce7577fSVaclav Hapla /*@C 30180ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 30190ce7577fSVaclav Hapla 3020a1cb98faSBarry Smith Not Collective 30210ce7577fSVaclav Hapla 30220ce7577fSVaclav Hapla Input Parameters: 3023a1cb98faSBarry Smith + dm - The `DMPLEX` 3024a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 30250ce7577fSVaclav Hapla 3026d8d19677SJose E. Roman Output Parameters: 302720f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 302820f4b53cSBarry Smith - pCones - An array of points which are on the in-edges for the point set `p` 30290ce7577fSVaclav Hapla 30300ce7577fSVaclav Hapla Level: intermediate 30310ce7577fSVaclav Hapla 30321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 30330ce7577fSVaclav Hapla @*/ 3034d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3035d71ae5a4SJacob Faibussowitsch { 30360ce7577fSVaclav Hapla PetscSection cs, newcs; 30370ce7577fSVaclav Hapla PetscInt *cones; 30380ce7577fSVaclav Hapla PetscInt *newarr = NULL; 30390ce7577fSVaclav Hapla PetscInt n; 30400ce7577fSVaclav Hapla 30410ce7577fSVaclav Hapla PetscFunctionBegin; 30429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 30439566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 30449566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 30450ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 30460ce7577fSVaclav Hapla if (pCones) { 30479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 30489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 30490ce7577fSVaclav Hapla } 30503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30510ce7577fSVaclav Hapla } 30520ce7577fSVaclav Hapla 3053af9eab45SVaclav Hapla /*@ 3054af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3055d4636a37SVaclav Hapla 3056a1cb98faSBarry Smith Not Collective 3057d4636a37SVaclav Hapla 3058d4636a37SVaclav Hapla Input Parameters: 3059a1cb98faSBarry Smith + dm - The `DMPLEX` 3060a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3061d4636a37SVaclav Hapla 3062d4636a37SVaclav Hapla Output Parameter: 3063af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points 3064d4636a37SVaclav Hapla 3065d4636a37SVaclav Hapla Level: advanced 3066d4636a37SVaclav Hapla 3067af9eab45SVaclav Hapla Notes: 306820f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3069af9eab45SVaclav Hapla 3070a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3071a1cb98faSBarry Smith 30721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3073a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3074d4636a37SVaclav Hapla @*/ 3075d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3076d71ae5a4SJacob Faibussowitsch { 3077af9eab45SVaclav Hapla IS *expandedPointsAll; 3078af9eab45SVaclav Hapla PetscInt depth; 3079d4636a37SVaclav Hapla 3080d4636a37SVaclav Hapla PetscFunctionBegin; 3081af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3082af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 30834f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 30849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3085af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 30869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 30879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 30883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3089af9eab45SVaclav Hapla } 3090af9eab45SVaclav Hapla 3091af9eab45SVaclav Hapla /*@ 3092af9eab45SVaclav 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). 3093af9eab45SVaclav Hapla 3094a1cb98faSBarry Smith Not Collective 3095af9eab45SVaclav Hapla 3096af9eab45SVaclav Hapla Input Parameters: 3097a1cb98faSBarry Smith + dm - The `DMPLEX` 3098a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3099af9eab45SVaclav Hapla 3100d8d19677SJose E. Roman Output Parameters: 3101a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3102af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3103af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3104af9eab45SVaclav Hapla 3105af9eab45SVaclav Hapla Level: advanced 3106af9eab45SVaclav Hapla 3107af9eab45SVaclav Hapla Notes: 3108a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3109af9eab45SVaclav Hapla 3110a4e35b19SJacob 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. 3111af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3112af9eab45SVaclav Hapla 3113a4e35b19SJacob 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\: 3114a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3115a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3116af9eab45SVaclav Hapla 31171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3118a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3119af9eab45SVaclav Hapla @*/ 3120d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3121d71ae5a4SJacob Faibussowitsch { 3122af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3123af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3124af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3125af9eab45SVaclav Hapla IS *expandedPoints_; 3126af9eab45SVaclav Hapla PetscSection *sections_; 3127af9eab45SVaclav Hapla 3128af9eab45SVaclav Hapla PetscFunctionBegin; 3129af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 31314f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 31324f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 31334f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 31349566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 31359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 31369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 31379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 31389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3139af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3140af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 31419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 31429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3143af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31449566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3145af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 31469566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 31479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3148af9eab45SVaclav Hapla } else { 31499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3150af9eab45SVaclav Hapla } 3151af9eab45SVaclav Hapla } 31529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 31539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 31549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3155af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 31569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 31579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3158af9eab45SVaclav Hapla if (cn > 1) { 31599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 31609566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3161af9eab45SVaclav Hapla } else { 3162af9eab45SVaclav Hapla newarr[co] = arr[i]; 3163af9eab45SVaclav Hapla } 3164af9eab45SVaclav Hapla } 31659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3166af9eab45SVaclav Hapla arr = newarr; 3167af9eab45SVaclav Hapla n = newn; 3168af9eab45SVaclav Hapla } 31699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3170af9eab45SVaclav Hapla *depth = depth_; 3171af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3172af9eab45SVaclav Hapla else { 31739566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 31749566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3175af9eab45SVaclav Hapla } 3176af9eab45SVaclav Hapla if (sections) *sections = sections_; 3177af9eab45SVaclav Hapla else { 31789566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 31799566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3180af9eab45SVaclav Hapla } 31813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3182af9eab45SVaclav Hapla } 3183af9eab45SVaclav Hapla 3184af9eab45SVaclav Hapla /*@ 3185a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3186af9eab45SVaclav Hapla 3187a1cb98faSBarry Smith Not Collective 3188af9eab45SVaclav Hapla 3189af9eab45SVaclav Hapla Input Parameters: 3190a1cb98faSBarry Smith + dm - The `DMPLEX` 3191a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3192af9eab45SVaclav Hapla 3193d8d19677SJose E. Roman Output Parameters: 3194a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3195af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3196af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3197af9eab45SVaclav Hapla 3198af9eab45SVaclav Hapla Level: advanced 3199af9eab45SVaclav Hapla 3200a1cb98faSBarry Smith Note: 3201a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3202af9eab45SVaclav Hapla 32031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3204a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3205af9eab45SVaclav Hapla @*/ 3206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3207d71ae5a4SJacob Faibussowitsch { 3208af9eab45SVaclav Hapla PetscInt d, depth_; 3209af9eab45SVaclav Hapla 3210af9eab45SVaclav Hapla PetscFunctionBegin; 32119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32121dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3213af9eab45SVaclav Hapla if (depth) *depth = 0; 3214af9eab45SVaclav Hapla if (expandedPoints) { 32159566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 32169566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3217af9eab45SVaclav Hapla } 3218af9eab45SVaclav Hapla if (sections) { 32199566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 32209566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3221af9eab45SVaclav Hapla } 32223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3223d4636a37SVaclav Hapla } 3224d4636a37SVaclav Hapla 3225552f7358SJed Brown /*@ 322692371b87SBarry 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 3227552f7358SJed Brown 3228a1cb98faSBarry Smith Not Collective 3229552f7358SJed Brown 3230552f7358SJed Brown Input Parameters: 323160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3232a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 323320f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p` 3234552f7358SJed Brown 3235552f7358SJed Brown Level: beginner 3236552f7358SJed Brown 3237a1cb98faSBarry Smith Note: 3238a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3239a1cb98faSBarry Smith 32401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3241552f7358SJed Brown @*/ 3242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3243d71ae5a4SJacob Faibussowitsch { 3244552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3245552f7358SJed Brown PetscInt dof, off, c; 3246552f7358SJed Brown 3247552f7358SJed Brown PetscFunctionBegin; 3248552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 32499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 32504f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 32519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3252db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3253db485b19SStefano Zampini PetscInt pStart, pEnd; 3254db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 325563a3b9bcSJacob 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); 3256552f7358SJed Brown for (c = 0; c < dof; ++c) { 325763a3b9bcSJacob 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); 3258552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3259552f7358SJed Brown } 3260db485b19SStefano Zampini } else { 3261db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3262db485b19SStefano Zampini } 32633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3264552f7358SJed Brown } 3265552f7358SJed Brown 3266552f7358SJed Brown /*@C 3267eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3268552f7358SJed Brown 3269a1cb98faSBarry Smith Not Collective 3270552f7358SJed Brown 3271552f7358SJed Brown Input Parameters: 327260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3273a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3274552f7358SJed Brown 3275552f7358SJed Brown Output Parameter: 327620f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 3277b5a892a1SMatthew G. Knepley integer giving the prescription for cone traversal. 3278552f7358SJed Brown 3279552f7358SJed Brown Level: beginner 3280552f7358SJed Brown 3281a1cb98faSBarry Smith Note: 3282b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3283b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3284a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3285b5a892a1SMatthew G. Knepley with the identity. 3286b5a892a1SMatthew G. Knepley 328760225df5SJacob Faibussowitsch Fortran Notes: 3288a1cb98faSBarry Smith You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3289a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 32903813dfbdSMatthew G Knepley 32911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3292552f7358SJed Brown @*/ 3293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3294d71ae5a4SJacob Faibussowitsch { 3295552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3296552f7358SJed Brown PetscInt off; 3297552f7358SJed Brown 3298552f7358SJed Brown PetscFunctionBegin; 3299552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 330076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3301552f7358SJed Brown PetscInt dof; 33029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33034f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3304552f7358SJed Brown } 33059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 33060d644c17SKarl Rupp 3307552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 33083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3309552f7358SJed Brown } 3310552f7358SJed Brown 3311552f7358SJed Brown /*@ 3312eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3313552f7358SJed Brown 3314a1cb98faSBarry Smith Not Collective 3315552f7358SJed Brown 3316552f7358SJed Brown Input Parameters: 331760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3318a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 3319b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations 3320b5a892a1SMatthew G. Knepley 3321552f7358SJed Brown Level: beginner 3322552f7358SJed Brown 3323a1cb98faSBarry Smith Notes: 3324a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3325a1cb98faSBarry Smith 3326a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3327a1cb98faSBarry Smith 33281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3329552f7358SJed Brown @*/ 3330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3331d71ae5a4SJacob Faibussowitsch { 3332552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3333552f7358SJed Brown PetscInt pStart, pEnd; 3334552f7358SJed Brown PetscInt dof, off, c; 3335552f7358SJed Brown 3336552f7358SJed Brown PetscFunctionBegin; 3337552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33394f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 33409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3341db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3342db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 334363a3b9bcSJacob 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); 3344552f7358SJed Brown for (c = 0; c < dof; ++c) { 3345552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3346552f7358SJed Brown 33479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 33481dca8a05SBarry 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); 3349552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3350552f7358SJed Brown } 3351db485b19SStefano Zampini } else { 3352db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3353db485b19SStefano Zampini } 33543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3355552f7358SJed Brown } 3356552f7358SJed Brown 33577cd05799SMatthew G. Knepley /*@ 3358eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 33597cd05799SMatthew G. Knepley 3360a1cb98faSBarry Smith Not Collective 33617cd05799SMatthew G. Knepley 33627cd05799SMatthew G. Knepley Input Parameters: 336360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3364a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33657cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 33667cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 33677cd05799SMatthew G. Knepley 33687cd05799SMatthew G. Knepley Level: beginner 33697cd05799SMatthew G. Knepley 33701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 33717cd05799SMatthew G. Knepley @*/ 3372d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3373d71ae5a4SJacob Faibussowitsch { 3374552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3375552f7358SJed Brown PetscInt pStart, pEnd; 3376552f7358SJed Brown PetscInt dof, off; 3377552f7358SJed Brown 3378552f7358SJed Brown PetscFunctionBegin; 3379552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3380a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 33819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 338263a3b9bcSJacob 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); 338363a3b9bcSJacob 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); 33849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 338563a3b9bcSJacob 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); 3386a03d55ffSStefano Zampini } 3387a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3388552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 33893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3390552f7358SJed Brown } 3391552f7358SJed Brown 33927cd05799SMatthew G. Knepley /*@ 3393eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 33947cd05799SMatthew G. Knepley 3395a1cb98faSBarry Smith Not Collective 33967cd05799SMatthew G. Knepley 33977cd05799SMatthew G. Knepley Input Parameters: 339860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3399a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34007cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34017cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 34027cd05799SMatthew G. Knepley 34037cd05799SMatthew G. Knepley Level: beginner 34047cd05799SMatthew G. Knepley 3405a1cb98faSBarry Smith Note: 3406a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3407b5a892a1SMatthew G. Knepley 34081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34097cd05799SMatthew G. Knepley @*/ 3410d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3411d71ae5a4SJacob Faibussowitsch { 341277c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 341377c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 341477c88f5bSMatthew G Knepley PetscInt dof, off; 341577c88f5bSMatthew G Knepley 341677c88f5bSMatthew G Knepley PetscFunctionBegin; 341777c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3418a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 34199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 342063a3b9bcSJacob 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); 34219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 342263a3b9bcSJacob 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); 3423a03d55ffSStefano Zampini } 3424a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 342577c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 34263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 342777c88f5bSMatthew G Knepley } 342877c88f5bSMatthew G Knepley 34299f4ada15SMatthew G. Knepley /*@C 34309f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 34319f4ada15SMatthew G. Knepley 34329f4ada15SMatthew G. Knepley Not collective 34339f4ada15SMatthew G. Knepley 34349f4ada15SMatthew G. Knepley Input Parameters: 34359f4ada15SMatthew G. Knepley + dm - The DMPlex 34369f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 34379f4ada15SMatthew G. Knepley 34389f4ada15SMatthew G. Knepley Output Parameters: 343920f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 344020f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34419f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34429f4ada15SMatthew G. Knepley 34439f4ada15SMatthew G. Knepley Level: beginner 34449f4ada15SMatthew G. Knepley 34459f4ada15SMatthew G. Knepley Notes: 34469f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34479f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 344820f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 34499f4ada15SMatthew G. Knepley with the identity. 34509f4ada15SMatthew G. Knepley 34519f4ada15SMatthew G. Knepley Fortran Notes: 345220f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 345320f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 34549f4ada15SMatthew G. Knepley 34551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 34569f4ada15SMatthew G. Knepley @*/ 34579f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 34589f4ada15SMatthew G. Knepley { 34599f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 34609f4ada15SMatthew G. Knepley 34619f4ada15SMatthew G. Knepley PetscFunctionBegin; 34629f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34639f4ada15SMatthew G. Knepley if (mesh->tr) { 34649f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 34659f4ada15SMatthew G. Knepley } else { 34669f4ada15SMatthew G. Knepley PetscInt off; 34679f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 34689f4ada15SMatthew G. Knepley PetscInt dof; 34699f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34709f4ada15SMatthew G. Knepley if (dof) { 34714f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 34724f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 34739f4ada15SMatthew G. Knepley } 34749f4ada15SMatthew G. Knepley } 34759f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3476072f5ffdSStefano Zampini if (cone) *cone = mesh->cones ? mesh->cones + off : NULL; // NULL + 0 is UB 3477072f5ffdSStefano Zampini if (ornt) *ornt = mesh->coneOrientations ? mesh->coneOrientations + off : NULL; 34789f4ada15SMatthew G. Knepley } 34793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34809f4ada15SMatthew G. Knepley } 34819f4ada15SMatthew G. Knepley 34829f4ada15SMatthew G. Knepley /*@C 34839f4ada15SMatthew G. Knepley DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG 34849f4ada15SMatthew G. Knepley 348520f4b53cSBarry Smith Not Collective 34869f4ada15SMatthew G. Knepley 34879f4ada15SMatthew G. Knepley Input Parameters: 34889f4ada15SMatthew G. Knepley + dm - The DMPlex 348920f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34909f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 349120f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 34929f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 34939f4ada15SMatthew G. Knepley 34949f4ada15SMatthew G. Knepley Level: beginner 34959f4ada15SMatthew G. Knepley 34969f4ada15SMatthew G. Knepley Notes: 34979f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 34989f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 349920f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35009f4ada15SMatthew G. Knepley with the identity. 35019f4ada15SMatthew G. Knepley 350260225df5SJacob Faibussowitsch Fortran Notes: 350320f4b53cSBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the returned array. 350420f4b53cSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 35059f4ada15SMatthew G. Knepley 35061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35079f4ada15SMatthew G. Knepley @*/ 35089f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35099f4ada15SMatthew G. Knepley { 35109f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35119f4ada15SMatthew G. Knepley 35129f4ada15SMatthew G. Knepley PetscFunctionBegin; 35139f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35149f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 35153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35169f4ada15SMatthew G. Knepley } 35179f4ada15SMatthew G. Knepley 3518552f7358SJed Brown /*@ 3519eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3520552f7358SJed Brown 3521a1cb98faSBarry Smith Not Collective 3522552f7358SJed Brown 3523552f7358SJed Brown Input Parameters: 352460225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3525a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3526552f7358SJed Brown 3527552f7358SJed Brown Output Parameter: 352820f4b53cSBarry Smith . size - The support size for point `p` 3529552f7358SJed Brown 3530552f7358SJed Brown Level: beginner 3531552f7358SJed Brown 35321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3533552f7358SJed Brown @*/ 3534d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3535d71ae5a4SJacob Faibussowitsch { 3536552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3537552f7358SJed Brown 3538552f7358SJed Brown PetscFunctionBegin; 3539552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35404f572ea9SToby Isaac PetscAssertPointer(size, 3); 35419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 35423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3543552f7358SJed Brown } 3544552f7358SJed Brown 3545552f7358SJed Brown /*@ 3546eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3547552f7358SJed Brown 3548a1cb98faSBarry Smith Not Collective 3549552f7358SJed Brown 3550552f7358SJed Brown Input Parameters: 355160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3552a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 355320f4b53cSBarry Smith - size - The support size for point `p` 3554552f7358SJed Brown 3555a1cb98faSBarry Smith Level: beginner 3556552f7358SJed Brown 3557552f7358SJed Brown Note: 355820f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3559552f7358SJed Brown 35601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3561552f7358SJed Brown @*/ 3562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3563d71ae5a4SJacob Faibussowitsch { 3564552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3565552f7358SJed Brown 3566552f7358SJed Brown PetscFunctionBegin; 3567552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 35693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3570552f7358SJed Brown } 3571552f7358SJed Brown 3572552f7358SJed Brown /*@C 3573eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3574552f7358SJed Brown 3575a1cb98faSBarry Smith Not Collective 3576552f7358SJed Brown 3577552f7358SJed Brown Input Parameters: 357860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3579a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3580552f7358SJed Brown 3581552f7358SJed Brown Output Parameter: 358220f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p` 3583552f7358SJed Brown 3584552f7358SJed Brown Level: beginner 3585552f7358SJed Brown 358660225df5SJacob Faibussowitsch Fortran Notes: 3587a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3588a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 35893813dfbdSMatthew G Knepley 35901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3591552f7358SJed Brown @*/ 3592d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3593d71ae5a4SJacob Faibussowitsch { 3594552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3595552f7358SJed Brown PetscInt off; 3596552f7358SJed Brown 3597552f7358SJed Brown PetscFunctionBegin; 3598552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35994f572ea9SToby Isaac PetscAssertPointer(support, 3); 36009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 3601072f5ffdSStefano Zampini *support = mesh->supports ? mesh->supports + off : NULL; //NULL + 0 is UB 36023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3603552f7358SJed Brown } 3604552f7358SJed Brown 3605552f7358SJed Brown /*@ 360692371b87SBarry 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 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()` 361320f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p` 3614552f7358SJed Brown 3615552f7358SJed Brown Level: beginner 3616552f7358SJed Brown 3617a1cb98faSBarry Smith Note: 3618a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3619a1cb98faSBarry Smith 36201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3621552f7358SJed Brown @*/ 3622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3623d71ae5a4SJacob Faibussowitsch { 3624552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3625552f7358SJed Brown PetscInt pStart, pEnd; 3626552f7358SJed Brown PetscInt dof, off, c; 3627552f7358SJed Brown 3628552f7358SJed Brown PetscFunctionBegin; 3629552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36324f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 36339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 363463a3b9bcSJacob 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); 3635552f7358SJed Brown for (c = 0; c < dof; ++c) { 363663a3b9bcSJacob 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); 3637552f7358SJed Brown mesh->supports[off + c] = support[c]; 3638552f7358SJed Brown } 36393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3640552f7358SJed Brown } 3641552f7358SJed Brown 36427cd05799SMatthew G. Knepley /*@ 3643eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 36447cd05799SMatthew G. Knepley 3645a1cb98faSBarry Smith Not Collective 36467cd05799SMatthew G. Knepley 36477cd05799SMatthew G. Knepley Input Parameters: 364860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3649a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36507cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 36517cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 36527cd05799SMatthew G. Knepley 36537cd05799SMatthew G. Knepley Level: beginner 36547cd05799SMatthew G. Knepley 36551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 36567cd05799SMatthew G. Knepley @*/ 3657d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3658d71ae5a4SJacob Faibussowitsch { 3659552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3660552f7358SJed Brown PetscInt pStart, pEnd; 3661552f7358SJed Brown PetscInt dof, off; 3662552f7358SJed Brown 3663552f7358SJed Brown PetscFunctionBegin; 3664552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 36669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 36679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 366863a3b9bcSJacob 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); 366963a3b9bcSJacob 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); 367063a3b9bcSJacob 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); 3671552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 36723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3673552f7358SJed Brown } 3674552f7358SJed Brown 3675b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3676d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3677d71ae5a4SJacob Faibussowitsch { 3678b5a892a1SMatthew G. Knepley switch (ct) { 3679b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3680b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3681b5a892a1SMatthew G. Knepley break; 3682b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3683b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3684b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3685b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3686b5a892a1SMatthew G. Knepley break; 3687b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3688b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3689b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3690b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3691b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3692b5a892a1SMatthew G. Knepley break; 3693d71ae5a4SJacob Faibussowitsch default: 3694d71ae5a4SJacob Faibussowitsch return o; 3695b5a892a1SMatthew G. Knepley } 3696b5a892a1SMatthew G. Knepley return o; 3697b5a892a1SMatthew G. Knepley } 3698b5a892a1SMatthew G. Knepley 3699b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3700d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3701d71ae5a4SJacob Faibussowitsch { 3702b5a892a1SMatthew G. Knepley switch (ct) { 3703b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3704b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3705b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3706b5a892a1SMatthew G. Knepley break; 3707b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3708b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3709b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3710b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3711b5a892a1SMatthew G. Knepley break; 3712b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3713b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3714b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3715b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3716b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3717b5a892a1SMatthew G. Knepley break; 3718d71ae5a4SJacob Faibussowitsch default: 3719d71ae5a4SJacob Faibussowitsch return o; 3720b5a892a1SMatthew G. Knepley } 3721b5a892a1SMatthew G. Knepley return o; 3722b5a892a1SMatthew G. Knepley } 3723b5a892a1SMatthew G. Knepley 3724b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3726d71ae5a4SJacob Faibussowitsch { 3727b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3728b5a892a1SMatthew G. Knepley 3729b5a892a1SMatthew G. Knepley PetscFunctionBegin; 37309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3731b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3732b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3733b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3734b5a892a1SMatthew G. Knepley 37359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 37369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 37379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3738b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3739b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3740b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3741b5a892a1SMatthew G. Knepley 37429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3743b5a892a1SMatthew G. Knepley switch (ct) { 3744b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 37459566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37469566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3747b5a892a1SMatthew G. Knepley break; 3748b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 37499566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37509566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37519566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3752b5a892a1SMatthew G. Knepley break; 3753b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 37549566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 37559566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 37569566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 37579566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3758b5a892a1SMatthew G. Knepley break; 3759d71ae5a4SJacob Faibussowitsch default: 3760d71ae5a4SJacob Faibussowitsch break; 3761b5a892a1SMatthew G. Knepley } 3762b5a892a1SMatthew G. Knepley } 3763b5a892a1SMatthew G. Knepley } 37643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3765b5a892a1SMatthew G. Knepley } 3766b5a892a1SMatthew G. Knepley 376709015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 376809015e70SStefano Zampini { 376909015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 377009015e70SStefano Zampini 377109015e70SStefano Zampini PetscFunctionBeginHot; 377209015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 377309015e70SStefano Zampini if (useCone) { 377409015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 377509015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 377609015e70SStefano Zampini } else { 377709015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 377809015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 377909015e70SStefano Zampini } 378009015e70SStefano Zampini } else { 378109015e70SStefano Zampini if (useCone) { 378209015e70SStefano Zampini const PetscSection s = mesh->coneSection; 378309015e70SStefano Zampini const PetscInt ps = p - s->pStart; 378409015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 378509015e70SStefano Zampini 378609015e70SStefano Zampini *size = s->atlasDof[ps]; 378709015e70SStefano Zampini *arr = mesh->cones + off; 378809015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 378909015e70SStefano Zampini } else { 379009015e70SStefano Zampini const PetscSection s = mesh->supportSection; 379109015e70SStefano Zampini const PetscInt ps = p - s->pStart; 379209015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 379309015e70SStefano Zampini 379409015e70SStefano Zampini *size = s->atlasDof[ps]; 379509015e70SStefano Zampini *arr = mesh->supports + off; 379609015e70SStefano Zampini } 379709015e70SStefano Zampini } 379809015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 379909015e70SStefano Zampini } 380009015e70SStefano Zampini 380109015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 380209015e70SStefano Zampini { 380309015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 380409015e70SStefano Zampini 380509015e70SStefano Zampini PetscFunctionBeginHot; 380609015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 380709015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 380809015e70SStefano Zampini } 380909015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 381009015e70SStefano Zampini } 381109015e70SStefano Zampini 3812d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3813d71ae5a4SJacob Faibussowitsch { 3814b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3815b5a892a1SMatthew G. Knepley PetscInt *closure; 3816b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3817b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3818b5a892a1SMatthew G. Knepley 3819b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3820b5a892a1SMatthew G. Knepley if (ornt) { 38219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3822476787b7SMatthew 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; 3823b5a892a1SMatthew G. Knepley } 3824b5a892a1SMatthew G. Knepley if (*points) { 3825b5a892a1SMatthew G. Knepley closure = *points; 3826b5a892a1SMatthew G. Knepley } else { 3827b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 38289566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 38299566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3830b5a892a1SMatthew G. Knepley } 383109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3832b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3833b5a892a1SMatthew G. Knepley closure[off++] = p; 3834b5a892a1SMatthew G. Knepley closure[off++] = 0; 3835b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3836b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3837b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3838b5a892a1SMatthew G. Knepley } 3839b5a892a1SMatthew G. Knepley } else { 38405f80ce2aSJacob Faibussowitsch const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt); 3841b5a892a1SMatthew G. Knepley 3842b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3843b5a892a1SMatthew G. Knepley closure[off++] = p; 3844b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3845b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3846b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3847b5a892a1SMatthew G. Knepley 38489566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3849b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3850b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3851b5a892a1SMatthew G. Knepley } 3852b5a892a1SMatthew G. Knepley } 385309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3854b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3855b5a892a1SMatthew G. Knepley if (points) *points = closure; 38563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3857b5a892a1SMatthew G. Knepley } 3858b5a892a1SMatthew G. Knepley 3859d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3860d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3861d71ae5a4SJacob Faibussowitsch { 3862b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 3863b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3864b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3865b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3866b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3867b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3868b5a892a1SMatthew G. Knepley 3869b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 38709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 387109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 38729566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3873b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3874b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3875b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 38769371c9d4SSatish Balay if (*points) { 38779371c9d4SSatish Balay pts = *points; 38789371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3879b5a892a1SMatthew G. Knepley c = 0; 3880b5a892a1SMatthew G. Knepley pts[c++] = point; 3881b5a892a1SMatthew G. Knepley pts[c++] = o; 38829566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 38839566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 38849371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 38859371c9d4SSatish Balay pts[c++] = closure[cl]; 38869371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 38879371c9d4SSatish Balay } 38889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 38899371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 38909371c9d4SSatish Balay pts[c++] = closure[cl]; 38919371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 38929371c9d4SSatish Balay } 38939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 3894b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 38959566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 3896b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 3897b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 3898b5a892a1SMatthew G. Knepley } 389909015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 3900b5a892a1SMatthew G. Knepley if (dim >= 3) { 3901b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 3902b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 3903b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 3904b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 3905b5a892a1SMatthew G. Knepley 39069566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 3907b5a892a1SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 390809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3909b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 3910b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 3911b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 3912b5a892a1SMatthew G. Knepley 39139371c9d4SSatish Balay for (i = 0; i < c; i += 2) 39149371c9d4SSatish Balay if (pts[i] == cp) break; 3915b5a892a1SMatthew G. Knepley if (i == c) { 39169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 3917b5a892a1SMatthew G. Knepley pts[c++] = cp; 3918b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 3919b5a892a1SMatthew G. Knepley } 3920b5a892a1SMatthew G. Knepley } 392109015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 3922b5a892a1SMatthew G. Knepley } 3923b5a892a1SMatthew G. Knepley } 3924b5a892a1SMatthew G. Knepley *numPoints = c / 2; 3925b5a892a1SMatthew G. Knepley *points = pts; 39263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3927b5a892a1SMatthew G. Knepley } 3928b5a892a1SMatthew G. Knepley 3929d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3930d71ae5a4SJacob Faibussowitsch { 3931b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3932b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 3933b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 3934b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 3935b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 3936b5a892a1SMatthew G. Knepley 3937b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 3939b5a892a1SMatthew G. Knepley if (depth == 1) { 39409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 39413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3942b5a892a1SMatthew G. Knepley } 39439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3944476787b7SMatthew 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; 3945c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 39469566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 39473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3948b5a892a1SMatthew G. Knepley } 39499566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3950b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 3951b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 3952b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39539566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 39549371c9d4SSatish Balay if (*points) { 39559371c9d4SSatish Balay closure = *points; 39569371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 3957b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 3958b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 3959b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 3960b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 3961b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3962b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 3963b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 3964b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 3965b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 3966b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 3967b5a892a1SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangment(qt, o); 396809015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 3969b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 3970b5a892a1SMatthew G. Knepley 3971b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 3972b5a892a1SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2; 397363a3b9bcSJacob 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); 3974b5a892a1SMatthew G. Knepley } 397509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3976b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3977b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 3978b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 3979b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 39809566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 3981b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 3982b5a892a1SMatthew G. Knepley PetscInt c; 3983b5a892a1SMatthew G. Knepley 3984b5a892a1SMatthew G. Knepley /* Check for duplicate */ 3985b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 3986b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 3987b5a892a1SMatthew G. Knepley } 3988b5a892a1SMatthew G. Knepley if (c == closureSize) { 3989b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 3990b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 3991b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 3992b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 3993b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 3994b5a892a1SMatthew G. Knepley } 3995b5a892a1SMatthew G. Knepley } 399609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 3997b5a892a1SMatthew G. Knepley } 39989566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 3999b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4000b5a892a1SMatthew G. Knepley if (points) *points = closure; 40013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4002b5a892a1SMatthew G. Knepley } 4003b5a892a1SMatthew G. Knepley 4004552f7358SJed Brown /*@C 4005eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4006552f7358SJed Brown 4007a1cb98faSBarry Smith Not Collective 4008552f7358SJed Brown 4009552f7358SJed Brown Input Parameters: 4010a1cb98faSBarry Smith + dm - The `DMPLEX` 4011b5a892a1SMatthew G. Knepley . p - The mesh point 4012a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4013552f7358SJed Brown 40146b867d5aSJose E. Roman Input/Output Parameter: 40156b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 401620f4b53cSBarry Smith if `NULL` on input, internal storage will be returned, otherwise the provided array is used 40176b867d5aSJose E. Roman 40186b867d5aSJose E. Roman Output Parameter: 401920f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4020552f7358SJed Brown 4021a1cb98faSBarry Smith Level: beginner 4022a1cb98faSBarry Smith 4023552f7358SJed Brown Note: 402420f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4025552f7358SJed Brown 402660225df5SJacob Faibussowitsch Fortran Notes: 402720f4b53cSBarry Smith The `numPoints` argument is not present in the Fortran binding since it is internal to the array. 40283813dfbdSMatthew G Knepley 40291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4030552f7358SJed Brown @*/ 4031d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4032d71ae5a4SJacob Faibussowitsch { 4033b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4034552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40354f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 40364f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 40379566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 40383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 40399bf0dad6SMatthew G. Knepley } 40409bf0dad6SMatthew G. Knepley 4041552f7358SJed Brown /*@C 4042eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4043552f7358SJed Brown 4044a1cb98faSBarry Smith Not Collective 4045552f7358SJed Brown 4046552f7358SJed Brown Input Parameters: 4047a1cb98faSBarry Smith + dm - The `DMPLEX` 4048b5a892a1SMatthew G. Knepley . p - The mesh point 4049a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 405020f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4051b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4052552f7358SJed Brown 4053a1cb98faSBarry Smith Level: beginner 4054a1cb98faSBarry Smith 4055552f7358SJed Brown Note: 405620f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4057552f7358SJed Brown 40581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4059552f7358SJed Brown @*/ 4060d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4061d71ae5a4SJacob Faibussowitsch { 4062b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4063552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40644ff43b2cSJed Brown if (numPoints) *numPoints = 0; 40659566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 40663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4067552f7358SJed Brown } 4068552f7358SJed Brown 4069552f7358SJed Brown /*@ 4070eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4071552f7358SJed Brown 4072a1cb98faSBarry Smith Not Collective 4073552f7358SJed Brown 4074552f7358SJed Brown Input Parameter: 407560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4076552f7358SJed Brown 4077552f7358SJed Brown Output Parameters: 4078552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4079552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4080552f7358SJed Brown 4081552f7358SJed Brown Level: beginner 4082552f7358SJed Brown 40831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4084552f7358SJed Brown @*/ 4085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4086d71ae5a4SJacob Faibussowitsch { 4087552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4088552f7358SJed Brown 4089552f7358SJed Brown PetscFunctionBegin; 4090552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40911baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 40921baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 40933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4094552f7358SJed Brown } 4095552f7358SJed Brown 4096d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4097d71ae5a4SJacob Faibussowitsch { 4098552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 40996302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4100552f7358SJed Brown 4101552f7358SJed Brown PetscFunctionBegin; 4102552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 41049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 41059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 41069566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 41076302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 41086302a7fbSVaclav Hapla if (maxSupportSize) { 41099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 41109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 41119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4112552f7358SJed Brown } 41133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4114552f7358SJed Brown } 4115552f7358SJed Brown 4116d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4117d71ae5a4SJacob Faibussowitsch { 4118552f7358SJed Brown PetscFunctionBegin; 41199566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 41209566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm)); 4121ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4122736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 412395602cf2SAlexis Marboeuf PetscSF sfNatural; 4124f94b4a02SBlaise Bourdin 41253dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 41269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 412795602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4128c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4129f94b4a02SBlaise Bourdin } 41303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4131552f7358SJed Brown } 4132552f7358SJed Brown 4133d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4134d71ae5a4SJacob Faibussowitsch { 41353dcd263cSBlaise Bourdin PetscInt i = 0; 41362adcc780SMatthew G. Knepley 41372adcc780SMatthew G. Knepley PetscFunctionBegin; 41389566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 41399566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4140c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 41413dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 41423dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 414395602cf2SAlexis Marboeuf PetscSF sfNatural; 41443dcd263cSBlaise Bourdin 41453dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 41469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4147c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 414895602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4149c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 41503dcd263cSBlaise Bourdin break; 41513dcd263cSBlaise Bourdin } 41523dcd263cSBlaise Bourdin } 41533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41542adcc780SMatthew G. Knepley } 41552adcc780SMatthew G. Knepley 4156552f7358SJed Brown /*@ 4157eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4158552f7358SJed Brown 4159a1cb98faSBarry Smith Not Collective 4160552f7358SJed Brown 4161552f7358SJed Brown Input Parameter: 416260225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4163552f7358SJed Brown 4164552f7358SJed Brown Level: beginner 4165552f7358SJed Brown 4166a1cb98faSBarry Smith Note: 4167a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4168a1cb98faSBarry Smith 41691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4170552f7358SJed Brown @*/ 4171d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4172d71ae5a4SJacob Faibussowitsch { 4173552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4174552f7358SJed Brown PetscInt *offsets; 4175552f7358SJed Brown PetscInt supportSize; 4176552f7358SJed Brown PetscInt pStart, pEnd, p; 4177552f7358SJed Brown 4178552f7358SJed Brown PetscFunctionBegin; 4179552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 418028b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 41819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4182552f7358SJed Brown /* Calculate support sizes */ 41839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4184552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4185552f7358SJed Brown PetscInt dof, off, c; 4186552f7358SJed Brown 41879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 41889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 418948a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4190552f7358SJed Brown } 41919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4192552f7358SJed Brown /* Calculate supports */ 41939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 41949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 41959566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4196552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4197552f7358SJed Brown PetscInt dof, off, c; 4198552f7358SJed Brown 41999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 42009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4201552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4202552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4203552f7358SJed Brown PetscInt offS; 4204552f7358SJed Brown 42059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 42060d644c17SKarl Rupp 4207552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4208552f7358SJed Brown ++offsets[q]; 4209552f7358SJed Brown } 4210552f7358SJed Brown } 42119566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 42129566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 42133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4214552f7358SJed Brown } 4215552f7358SJed Brown 4216d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4217d71ae5a4SJacob Faibussowitsch { 4218277ea44aSLisandro Dalcin IS stratumIS; 4219277ea44aSLisandro Dalcin 4220277ea44aSLisandro Dalcin PetscFunctionBegin; 42213ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 422276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4223277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4224277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 42259566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4226277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 42279566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 42289371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 42299371c9d4SSatish Balay overlap = PETSC_TRUE; 42309371c9d4SSatish Balay break; 42319371c9d4SSatish Balay } 4232277ea44aSLisandro Dalcin } 423363a3b9bcSJacob 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); 4234277ea44aSLisandro Dalcin } 42359566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 42369566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 42379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 42383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4239277ea44aSLisandro Dalcin } 4240277ea44aSLisandro Dalcin 4241e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4242e91fa0a1SMatthew G. Knepley { 4243e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4244e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4245e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4246e91fa0a1SMatthew G. Knepley 4247e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4248e91fa0a1SMatthew G. Knepley { 4249e91fa0a1SMatthew G. Knepley DMLabel label2; 4250e91fa0a1SMatthew G. Knepley 4251e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4252e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4253e91fa0a1SMatthew G. Knepley } 4254e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4255e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4256e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4257e91fa0a1SMatthew G. Knepley 4258e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4259e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4260e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4261e91fa0a1SMatthew G. Knepley } 4262e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4263e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4264e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4265e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4266e91fa0a1SMatthew G. Knepley } 4267e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4268e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4269e91fa0a1SMatthew G. Knepley PetscInt d; 4270e91fa0a1SMatthew G. Knepley 4271e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4272e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4273e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4274e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4275e91fa0a1SMatthew G. Knepley } 4276e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4277e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4278e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4279e91fa0a1SMatthew G. Knepley } 4280e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4281e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4282e91fa0a1SMatthew G. Knepley } 4283e91fa0a1SMatthew G. Knepley 4284e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4285e91fa0a1SMatthew G. Knepley { 4286e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4287e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4288e91fa0a1SMatthew G. Knepley 4289e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4290e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4291e91fa0a1SMatthew G. Knepley { 4292e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4293e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4294e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4295e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4296e91fa0a1SMatthew G. Knepley 4297e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4298e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4299e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4300e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4301e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4302e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4303e91fa0a1SMatthew G. Knepley ++numRoots; 4304e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4305e91fa0a1SMatthew G. Knepley ++numLeaves; 4306e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4307e91fa0a1SMatthew G. Knepley /* Isolated points */ 4308e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4309e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4310e91fa0a1SMatthew G. Knepley } 4311e91fa0a1SMatthew G. Knepley } 4312e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4313e91fa0a1SMatthew G. Knepley } 4314e91fa0a1SMatthew G. Knepley 4315e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4316e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4317e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4318e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4319e91fa0a1SMatthew G. Knepley 4320e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4321e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4322e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4323e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4324e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4325e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4326e91fa0a1SMatthew G. Knepley } 4327e91fa0a1SMatthew G. Knepley } 4328e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4329e91fa0a1SMatthew G. Knepley } else { 4330e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4331e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4332e91fa0a1SMatthew G. Knepley 4333e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4334e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4335e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4336e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4337e91fa0a1SMatthew G. Knepley 4338e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4339e91fa0a1SMatthew G. Knepley const PetscInt *support; 4340e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4341e91fa0a1SMatthew G. Knepley 4342e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4343e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4344e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4345e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4346e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4347e91fa0a1SMatthew G. Knepley } 4348e91fa0a1SMatthew G. Knepley } 4349e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4350e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4351e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4352e91fa0a1SMatthew G. Knepley } 4353e91fa0a1SMatthew G. Knepley } 4354e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4355e91fa0a1SMatthew G. Knepley } 4356e91fa0a1SMatthew G. Knepley 4357552f7358SJed Brown /*@ 4358a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4359552f7358SJed Brown 436020f4b53cSBarry Smith Collective 4361552f7358SJed Brown 4362552f7358SJed Brown Input Parameter: 436360225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4364552f7358SJed Brown 4365a1cb98faSBarry Smith Level: beginner 4366552f7358SJed Brown 4367552f7358SJed Brown Notes: 4368a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4369a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4370a4e35b19SJacob Faibussowitsch 4371a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4372a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4373a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4374b1bb481bSMatthew 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 4375a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4376a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4377a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4378552f7358SJed Brown 4379b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4380b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4381b1bb481bSMatthew 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 4382b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4383a1cb98faSBarry Smith .vb 4384a1cb98faSBarry Smith cone(c0) = {e0, v2} 4385a1cb98faSBarry Smith cone(e0) = {v0, v1} 4386a1cb98faSBarry Smith .ve 4387a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4388a1cb98faSBarry Smith .vb 4389a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4390a1cb98faSBarry Smith depth 1 = {e0, c0} 4391a1cb98faSBarry Smith .ve 4392b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4393b1bb481bSMatthew Knepley 4394a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4395552f7358SJed Brown 43961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4397552f7358SJed Brown @*/ 4398d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4399d71ae5a4SJacob Faibussowitsch { 4400df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4401aa50250dSMatthew G. Knepley DMLabel label; 4402e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4403552f7358SJed Brown 4404552f7358SJed Brown PetscFunctionBegin; 4405552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 44069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4407277ea44aSLisandro Dalcin 4408e91fa0a1SMatthew G. Knepley // Create depth label 44099566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 44109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4411277ea44aSLisandro Dalcin 4412e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4413e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4414e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4415552f7358SJed Brown 4416bf4602e4SToby Isaac { /* just in case there is an empty process */ 4417bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4418bf4602e4SToby Isaac 44199566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4420712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 442148a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4422bf4602e4SToby Isaac } 44239566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 44249566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 44253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4426552f7358SJed Brown } 4427552f7358SJed Brown 4428d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4429d71ae5a4SJacob Faibussowitsch { 4430412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4431412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4432ba2698f1SMatthew G. Knepley 4433412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 44349566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 44359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 44369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4437ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4438ba2698f1SMatthew G. Knepley if (depth <= 1) { 4439ba2698f1SMatthew G. Knepley switch (pdepth) { 4440d71ae5a4SJacob Faibussowitsch case 0: 4441d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4442d71ae5a4SJacob Faibussowitsch break; 4443ba2698f1SMatthew G. Knepley case 1: 4444ba2698f1SMatthew G. Knepley switch (coneSize) { 4445d71ae5a4SJacob Faibussowitsch case 2: 4446d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4447d71ae5a4SJacob Faibussowitsch break; 4448d71ae5a4SJacob Faibussowitsch case 3: 4449d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4450d71ae5a4SJacob Faibussowitsch break; 4451ba2698f1SMatthew G. Knepley case 4: 4452ba2698f1SMatthew G. Knepley switch (dim) { 4453d71ae5a4SJacob Faibussowitsch case 2: 4454d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4455d71ae5a4SJacob Faibussowitsch break; 4456d71ae5a4SJacob Faibussowitsch case 3: 4457d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4458d71ae5a4SJacob Faibussowitsch break; 4459d71ae5a4SJacob Faibussowitsch default: 4460d71ae5a4SJacob Faibussowitsch break; 4461ba2698f1SMatthew G. Knepley } 4462ba2698f1SMatthew G. Knepley break; 4463d71ae5a4SJacob Faibussowitsch case 5: 4464d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4465d71ae5a4SJacob Faibussowitsch break; 4466d71ae5a4SJacob Faibussowitsch case 6: 4467d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4468d71ae5a4SJacob Faibussowitsch break; 4469d71ae5a4SJacob Faibussowitsch case 8: 4470d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4471d71ae5a4SJacob Faibussowitsch break; 4472d71ae5a4SJacob Faibussowitsch default: 4473d71ae5a4SJacob Faibussowitsch break; 4474ba2698f1SMatthew G. Knepley } 4475ba2698f1SMatthew G. Knepley } 4476ba2698f1SMatthew G. Knepley } else { 4477ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4478ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4479ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4480ba2698f1SMatthew G. Knepley switch (dim) { 4481ba2698f1SMatthew G. Knepley case 1: 4482ba2698f1SMatthew G. Knepley switch (coneSize) { 4483d71ae5a4SJacob Faibussowitsch case 2: 4484d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4485d71ae5a4SJacob Faibussowitsch break; 4486d71ae5a4SJacob Faibussowitsch default: 4487d71ae5a4SJacob Faibussowitsch break; 4488ba2698f1SMatthew G. Knepley } 4489ba2698f1SMatthew G. Knepley break; 4490ba2698f1SMatthew G. Knepley case 2: 4491ba2698f1SMatthew G. Knepley switch (coneSize) { 4492d71ae5a4SJacob Faibussowitsch case 3: 4493d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4494d71ae5a4SJacob Faibussowitsch break; 4495d71ae5a4SJacob Faibussowitsch case 4: 4496d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4497d71ae5a4SJacob Faibussowitsch break; 4498d71ae5a4SJacob Faibussowitsch default: 4499d71ae5a4SJacob Faibussowitsch break; 4500ba2698f1SMatthew G. Knepley } 4501ba2698f1SMatthew G. Knepley break; 4502ba2698f1SMatthew G. Knepley case 3: 4503ba2698f1SMatthew G. Knepley switch (coneSize) { 4504d71ae5a4SJacob Faibussowitsch case 4: 4505d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4506d71ae5a4SJacob Faibussowitsch break; 45079371c9d4SSatish Balay case 5: { 4508da9060c4SMatthew G. Knepley const PetscInt *cone; 4509da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4510da9060c4SMatthew G. Knepley 45119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 45129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4513da9060c4SMatthew G. Knepley switch (faceConeSize) { 4514d71ae5a4SJacob Faibussowitsch case 3: 4515d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4516d71ae5a4SJacob Faibussowitsch break; 4517d71ae5a4SJacob Faibussowitsch case 4: 4518d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4519d71ae5a4SJacob Faibussowitsch break; 4520da9060c4SMatthew G. Knepley } 45219371c9d4SSatish Balay } break; 4522d71ae5a4SJacob Faibussowitsch case 6: 4523d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4524d71ae5a4SJacob Faibussowitsch break; 4525d71ae5a4SJacob Faibussowitsch default: 4526d71ae5a4SJacob Faibussowitsch break; 4527ba2698f1SMatthew G. Knepley } 4528ba2698f1SMatthew G. Knepley break; 4529d71ae5a4SJacob Faibussowitsch default: 4530d71ae5a4SJacob Faibussowitsch break; 4531ba2698f1SMatthew G. Knepley } 4532ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4533ba2698f1SMatthew G. Knepley switch (coneSize) { 4534d71ae5a4SJacob Faibussowitsch case 2: 4535d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4536d71ae5a4SJacob Faibussowitsch break; 4537d71ae5a4SJacob Faibussowitsch case 3: 4538d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4539d71ae5a4SJacob Faibussowitsch break; 4540d71ae5a4SJacob Faibussowitsch case 4: 4541d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4542d71ae5a4SJacob Faibussowitsch break; 4543d71ae5a4SJacob Faibussowitsch default: 4544d71ae5a4SJacob Faibussowitsch break; 4545ba2698f1SMatthew G. Knepley } 4546ba2698f1SMatthew G. Knepley } 4547ba2698f1SMatthew G. Knepley } 4548412e9a14SMatthew G. Knepley *pt = ct; 45493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4550ba2698f1SMatthew G. Knepley } 4551412e9a14SMatthew G. Knepley 4552412e9a14SMatthew G. Knepley /*@ 4553412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4554412e9a14SMatthew G. Knepley 455520f4b53cSBarry Smith Collective 4556412e9a14SMatthew G. Knepley 4557412e9a14SMatthew G. Knepley Input Parameter: 455860225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4559412e9a14SMatthew G. Knepley 4560412e9a14SMatthew G. Knepley Level: developer 4561412e9a14SMatthew G. Knepley 4562a1cb98faSBarry Smith Note: 4563a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4564a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4565a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4566412e9a14SMatthew G. Knepley 4567a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4568a1cb98faSBarry Smith 45691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4570412e9a14SMatthew G. Knepley @*/ 4571d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4572d71ae5a4SJacob Faibussowitsch { 4573412e9a14SMatthew G. Knepley DM_Plex *mesh; 4574412e9a14SMatthew G. Knepley DMLabel ctLabel; 4575412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4576412e9a14SMatthew G. Knepley 4577412e9a14SMatthew G. Knepley PetscFunctionBegin; 4578412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4579412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 45809566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 45819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 45829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 458321027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 458421027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4585412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4586327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4587412e9a14SMatthew G. Knepley PetscInt pdepth; 4588412e9a14SMatthew G. Knepley 45899566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 45909566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4591476787b7SMatthew 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); 45929566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 459321027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = ct; 4594412e9a14SMatthew G. Knepley } 45959566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 45969566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 45973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4598ba2698f1SMatthew G. Knepley } 4599ba2698f1SMatthew G. Knepley 4600552f7358SJed Brown /*@C 4601552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4602552f7358SJed Brown 4603552f7358SJed Brown Not Collective 4604552f7358SJed Brown 4605552f7358SJed Brown Input Parameters: 4606a1cb98faSBarry Smith + dm - The `DMPLEX` object 4607552f7358SJed Brown . numPoints - The number of input points for the join 4608552f7358SJed Brown - points - The input points 4609552f7358SJed Brown 4610552f7358SJed Brown Output Parameters: 4611552f7358SJed Brown + numCoveredPoints - The number of points in the join 4612552f7358SJed Brown - coveredPoints - The points in the join 4613552f7358SJed Brown 4614552f7358SJed Brown Level: intermediate 4615552f7358SJed Brown 4616a1cb98faSBarry Smith Note: 4617a1cb98faSBarry Smith Currently, this is restricted to a single level join 4618552f7358SJed Brown 461960225df5SJacob Faibussowitsch Fortran Notes: 462020f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 46213813dfbdSMatthew G Knepley 46221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4623552f7358SJed Brown @*/ 4624d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4625d71ae5a4SJacob Faibussowitsch { 4626552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4627552f7358SJed Brown PetscInt *join[2]; 4628552f7358SJed Brown PetscInt joinSize, i = 0; 4629552f7358SJed Brown PetscInt dof, off, p, c, m; 46306302a7fbSVaclav Hapla PetscInt maxSupportSize; 4631552f7358SJed Brown 4632552f7358SJed Brown PetscFunctionBegin; 4633552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46344f572ea9SToby Isaac PetscAssertPointer(points, 3); 46354f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 46364f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46376302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 46386302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 46396302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4640552f7358SJed Brown /* Copy in support of first point */ 46419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 46429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4643ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4644552f7358SJed Brown /* Check each successive support */ 4645552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4646552f7358SJed Brown PetscInt newJoinSize = 0; 4647552f7358SJed Brown 46489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 46499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4650552f7358SJed Brown for (c = 0; c < dof; ++c) { 4651552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4652552f7358SJed Brown 4653552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4654552f7358SJed Brown if (point == join[i][m]) { 4655552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4656552f7358SJed Brown break; 4657552f7358SJed Brown } 4658552f7358SJed Brown } 4659552f7358SJed Brown } 4660552f7358SJed Brown joinSize = newJoinSize; 4661552f7358SJed Brown i = 1 - i; 4662552f7358SJed Brown } 4663552f7358SJed Brown *numCoveredPoints = joinSize; 4664552f7358SJed Brown *coveredPoints = join[i]; 46656302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 46663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4667552f7358SJed Brown } 4668552f7358SJed Brown 4669552f7358SJed Brown /*@C 4670552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 4671552f7358SJed Brown 4672552f7358SJed Brown Not Collective 4673552f7358SJed Brown 4674552f7358SJed Brown Input Parameters: 4675a1cb98faSBarry Smith + dm - The `DMPLEX` object 4676552f7358SJed Brown . numPoints - The number of input points for the join 4677552f7358SJed Brown - points - The input points 4678552f7358SJed Brown 4679552f7358SJed Brown Output Parameters: 4680552f7358SJed Brown + numCoveredPoints - The number of points in the join 4681552f7358SJed Brown - coveredPoints - The points in the join 4682552f7358SJed Brown 4683552f7358SJed Brown Level: intermediate 4684552f7358SJed Brown 468560225df5SJacob Faibussowitsch Fortran Notes: 468620f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4687a1cb98faSBarry Smith 46881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4689552f7358SJed Brown @*/ 4690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4691d71ae5a4SJacob Faibussowitsch { 4692552f7358SJed Brown PetscFunctionBegin; 4693552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 46944f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 46954f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 46964f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 46979566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4698d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 46993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4700552f7358SJed Brown } 4701552f7358SJed Brown 4702552f7358SJed Brown /*@C 4703552f7358SJed Brown DMPlexGetFullJoin - Get 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()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4722552f7358SJed Brown @*/ 4723d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4724d71ae5a4SJacob Faibussowitsch { 4725552f7358SJed Brown PetscInt *offsets, **closures; 4726552f7358SJed Brown PetscInt *join[2]; 4727552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 472824c766afSToby Isaac PetscInt p, d, c, m, ms; 4729552f7358SJed Brown 4730552f7358SJed Brown PetscFunctionBegin; 4731552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47324f572ea9SToby Isaac PetscAssertPointer(points, 3); 47334f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47344f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4735552f7358SJed Brown 47369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 47379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 47389566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47396302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 474024c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 47419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 47429566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4743552f7358SJed Brown 4744552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4745552f7358SJed Brown PetscInt closureSize; 4746552f7358SJed Brown 47479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 47480d644c17SKarl Rupp 4749552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4750552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4751552f7358SJed Brown PetscInt pStart, pEnd, i; 4752552f7358SJed Brown 47539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4754552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4755552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4756552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4757552f7358SJed Brown break; 4758552f7358SJed Brown } 4759552f7358SJed Brown } 4760552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4761552f7358SJed Brown } 476263a3b9bcSJacob 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); 4763552f7358SJed Brown } 4764552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4765552f7358SJed Brown PetscInt dof; 4766552f7358SJed Brown 4767552f7358SJed Brown /* Copy in support of first point */ 4768552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4769ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4770552f7358SJed Brown /* Check each successive cone */ 4771552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4772552f7358SJed Brown PetscInt newJoinSize = 0; 4773552f7358SJed Brown 4774552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4775552f7358SJed Brown for (c = 0; c < dof; ++c) { 4776552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4777552f7358SJed Brown 4778552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4779552f7358SJed Brown if (point == join[i][m]) { 4780552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4781552f7358SJed Brown break; 4782552f7358SJed Brown } 4783552f7358SJed Brown } 4784552f7358SJed Brown } 4785552f7358SJed Brown joinSize = newJoinSize; 4786552f7358SJed Brown i = 1 - i; 4787552f7358SJed Brown } 4788552f7358SJed Brown if (joinSize) break; 4789552f7358SJed Brown } 4790552f7358SJed Brown *numCoveredPoints = joinSize; 4791552f7358SJed Brown *coveredPoints = join[i]; 479248a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 47939566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 47949566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 47956302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 47963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4797552f7358SJed Brown } 4798552f7358SJed Brown 4799552f7358SJed Brown /*@C 4800552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4801552f7358SJed Brown 4802552f7358SJed Brown Not Collective 4803552f7358SJed Brown 4804552f7358SJed Brown Input Parameters: 4805a1cb98faSBarry Smith + dm - The `DMPLEX` object 4806552f7358SJed Brown . numPoints - The number of input points for the meet 4807552f7358SJed Brown - points - The input points 4808552f7358SJed Brown 4809552f7358SJed Brown Output Parameters: 481060225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 481160225df5SJacob Faibussowitsch - coveringPoints - The points in the meet 4812552f7358SJed Brown 4813552f7358SJed Brown Level: intermediate 4814552f7358SJed Brown 4815a1cb98faSBarry Smith Note: 4816a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4817552f7358SJed Brown 48183813dfbdSMatthew G Knepley Fortran Notes: 481920f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48203813dfbdSMatthew G Knepley 48211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4822552f7358SJed Brown @*/ 4823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 4824d71ae5a4SJacob Faibussowitsch { 4825552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4826552f7358SJed Brown PetscInt *meet[2]; 4827552f7358SJed Brown PetscInt meetSize, i = 0; 4828552f7358SJed Brown PetscInt dof, off, p, c, m; 48296302a7fbSVaclav Hapla PetscInt maxConeSize; 4830552f7358SJed Brown 4831552f7358SJed Brown PetscFunctionBegin; 4832552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48334f572ea9SToby Isaac PetscAssertPointer(points, 3); 48344f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 48354f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 48366302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 48376302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 48386302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4839552f7358SJed Brown /* Copy in cone of first point */ 48409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 48419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4842ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4843552f7358SJed Brown /* Check each successive cone */ 4844552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4845552f7358SJed Brown PetscInt newMeetSize = 0; 4846552f7358SJed Brown 48479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 48489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4849552f7358SJed Brown for (c = 0; c < dof; ++c) { 4850552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 4851552f7358SJed Brown 4852552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4853552f7358SJed Brown if (point == meet[i][m]) { 4854552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4855552f7358SJed Brown break; 4856552f7358SJed Brown } 4857552f7358SJed Brown } 4858552f7358SJed Brown } 4859552f7358SJed Brown meetSize = newMeetSize; 4860552f7358SJed Brown i = 1 - i; 4861552f7358SJed Brown } 4862552f7358SJed Brown *numCoveringPoints = meetSize; 4863552f7358SJed Brown *coveringPoints = meet[i]; 48646302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 48653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4866552f7358SJed Brown } 4867552f7358SJed Brown 4868552f7358SJed Brown /*@C 4869552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 4870552f7358SJed Brown 4871552f7358SJed Brown Not Collective 4872552f7358SJed Brown 4873552f7358SJed Brown Input Parameters: 4874a1cb98faSBarry Smith + dm - The `DMPLEX` object 4875552f7358SJed Brown . numPoints - The number of input points for the meet 4876552f7358SJed Brown - points - The input points 4877552f7358SJed Brown 4878552f7358SJed Brown Output Parameters: 4879552f7358SJed Brown + numCoveredPoints - The number of points in the meet 4880552f7358SJed Brown - coveredPoints - The points in the meet 4881552f7358SJed Brown 4882552f7358SJed Brown Level: intermediate 4883552f7358SJed Brown 488460225df5SJacob Faibussowitsch Fortran Notes: 488520f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 48863813dfbdSMatthew G Knepley 48871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 4888552f7358SJed Brown @*/ 4889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4890d71ae5a4SJacob Faibussowitsch { 4891552f7358SJed Brown PetscFunctionBegin; 4892552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48934f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 48944f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 48954f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 48969566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4897d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 48983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4899552f7358SJed Brown } 4900552f7358SJed Brown 4901552f7358SJed Brown /*@C 4902552f7358SJed Brown DMPlexGetFullMeet - Get 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()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4921552f7358SJed Brown @*/ 4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 4923d71ae5a4SJacob Faibussowitsch { 4924552f7358SJed Brown PetscInt *offsets, **closures; 4925552f7358SJed Brown PetscInt *meet[2]; 4926552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 492724c766afSToby Isaac PetscInt p, h, c, m, mc; 4928552f7358SJed Brown 4929552f7358SJed Brown PetscFunctionBegin; 4930552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49314f572ea9SToby Isaac PetscAssertPointer(points, 3); 49324f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 49334f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4934552f7358SJed Brown 49359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 49369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 49379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49386302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 493924c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 49409566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 49419566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 4942552f7358SJed Brown 4943552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4944552f7358SJed Brown PetscInt closureSize; 4945552f7358SJed Brown 49469566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 49470d644c17SKarl Rupp 4948552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 4949552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4950552f7358SJed Brown PetscInt pStart, pEnd, i; 4951552f7358SJed Brown 49529566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 4953552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 4954552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4955552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 4956552f7358SJed Brown break; 4957552f7358SJed Brown } 4958552f7358SJed Brown } 4959552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 4960552f7358SJed Brown } 496163a3b9bcSJacob 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); 4962552f7358SJed Brown } 4963552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 4964552f7358SJed Brown PetscInt dof; 4965552f7358SJed Brown 4966552f7358SJed Brown /* Copy in cone of first point */ 4967552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 4968ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 4969552f7358SJed Brown /* Check each successive cone */ 4970552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 4971552f7358SJed Brown PetscInt newMeetSize = 0; 4972552f7358SJed Brown 4973552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 4974552f7358SJed Brown for (c = 0; c < dof; ++c) { 4975552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 4976552f7358SJed Brown 4977552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 4978552f7358SJed Brown if (point == meet[i][m]) { 4979552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 4980552f7358SJed Brown break; 4981552f7358SJed Brown } 4982552f7358SJed Brown } 4983552f7358SJed Brown } 4984552f7358SJed Brown meetSize = newMeetSize; 4985552f7358SJed Brown i = 1 - i; 4986552f7358SJed Brown } 4987552f7358SJed Brown if (meetSize) break; 4988552f7358SJed Brown } 4989552f7358SJed Brown *numCoveredPoints = meetSize; 4990552f7358SJed Brown *coveredPoints = meet[i]; 499148a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 49929566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 49939566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 49946302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 49953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4996552f7358SJed Brown } 4997552f7358SJed Brown 49984e3744c5SMatthew G. Knepley /*@C 4999a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 50004e3744c5SMatthew G. Knepley 50014e3744c5SMatthew G. Knepley Not Collective 50024e3744c5SMatthew G. Knepley 50034e3744c5SMatthew G. Knepley Input Parameters: 5004a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5005a1cb98faSBarry Smith - dmB - A `DMPLEX` object 50064e3744c5SMatthew G. Knepley 50072fe279fdSBarry Smith Output Parameter: 5008a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 50094e3744c5SMatthew G. Knepley 50104e3744c5SMatthew G. Knepley Level: intermediate 50114e3744c5SMatthew G. Knepley 5012a1cb98faSBarry Smith Note: 50133c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 50144e3744c5SMatthew G. Knepley 50151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50164e3744c5SMatthew G. Knepley @*/ 5017d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5018d71ae5a4SJacob Faibussowitsch { 50194e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 50204e3744c5SMatthew G. Knepley 50214e3744c5SMatthew G. Knepley PetscFunctionBegin; 50224e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 50234e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 50244f572ea9SToby Isaac PetscAssertPointer(equal, 3); 50254e3744c5SMatthew G. Knepley 50264e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 50279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 50289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 50293ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 50309566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 50319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 50323ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 50334e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 50344e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 50354e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 50364e3744c5SMatthew G. Knepley 50379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 50389566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 50399566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 50409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 50419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 50429566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 50433ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50444e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 50453ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50463ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 50474e3744c5SMatthew G. Knepley } 50489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 50499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 50509566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 50519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 50523ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 50534e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 50543ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 50554e3744c5SMatthew G. Knepley } 50564e3744c5SMatthew G. Knepley } 50574e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 50583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50594e3744c5SMatthew G. Knepley } 50604e3744c5SMatthew G. Knepley 50617cd05799SMatthew G. Knepley /*@C 50627cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 50637cd05799SMatthew G. Knepley 50647cd05799SMatthew G. Knepley Not Collective 50657cd05799SMatthew G. Knepley 50667cd05799SMatthew G. Knepley Input Parameters: 5067a1cb98faSBarry Smith + dm - The `DMPLEX` 50687cd05799SMatthew G. Knepley . cellDim - The cell dimension 50697cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 50707cd05799SMatthew G. Knepley 50712fe279fdSBarry Smith Output Parameter: 50727cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 50737cd05799SMatthew G. Knepley 50747cd05799SMatthew G. Knepley Level: developer 50757cd05799SMatthew G. Knepley 5076a1cb98faSBarry Smith Note: 50777cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 50787cd05799SMatthew G. Knepley 50791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 50807cd05799SMatthew G. Knepley @*/ 5081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5082d71ae5a4SJacob Faibussowitsch { 508382f516ccSBarry Smith MPI_Comm comm; 5084552f7358SJed Brown 5085552f7358SJed Brown PetscFunctionBegin; 50869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 50874f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5088552f7358SJed Brown switch (cellDim) { 5089d71ae5a4SJacob Faibussowitsch case 0: 5090d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5091d71ae5a4SJacob Faibussowitsch break; 5092d71ae5a4SJacob Faibussowitsch case 1: 5093d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5094d71ae5a4SJacob Faibussowitsch break; 5095552f7358SJed Brown case 2: 5096552f7358SJed Brown switch (numCorners) { 509719436ca2SJed Brown case 3: /* triangle */ 509819436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5099552f7358SJed Brown break; 510019436ca2SJed Brown case 4: /* quadrilateral */ 510119436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5102552f7358SJed Brown break; 510319436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 510419436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5105552f7358SJed Brown break; 510619436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 510719436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5108552f7358SJed Brown break; 5109d71ae5a4SJacob Faibussowitsch default: 5110d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5111552f7358SJed Brown } 5112552f7358SJed Brown break; 5113552f7358SJed Brown case 3: 5114552f7358SJed Brown switch (numCorners) { 511519436ca2SJed Brown case 4: /* tetradehdron */ 511619436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5117552f7358SJed Brown break; 511819436ca2SJed Brown case 6: /* tet cohesive cells */ 511919436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5120552f7358SJed Brown break; 512119436ca2SJed Brown case 8: /* hexahedron */ 512219436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5123552f7358SJed Brown break; 512419436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 512519436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5126552f7358SJed Brown break; 512719436ca2SJed Brown case 10: /* quadratic tetrahedron */ 512819436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5129552f7358SJed Brown break; 513019436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 513119436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5132552f7358SJed Brown break; 513319436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 513419436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5135552f7358SJed Brown break; 513619436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 513719436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5138552f7358SJed Brown break; 5139d71ae5a4SJacob Faibussowitsch default: 5140d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5141552f7358SJed Brown } 5142552f7358SJed Brown break; 5143d71ae5a4SJacob Faibussowitsch default: 5144d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5145552f7358SJed Brown } 51463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5147552f7358SJed Brown } 5148552f7358SJed Brown 5149552f7358SJed Brown /*@ 5150a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5151552f7358SJed Brown 5152552f7358SJed Brown Not Collective 5153552f7358SJed Brown 5154aa50250dSMatthew G. Knepley Input Parameter: 5155a1cb98faSBarry Smith . dm - The `DMPLEX` object 5156552f7358SJed Brown 5157aa50250dSMatthew G. Knepley Output Parameter: 5158a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5159552f7358SJed Brown 5160552f7358SJed Brown Level: developer 5161552f7358SJed Brown 51621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5163aa50250dSMatthew G. Knepley @*/ 5164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5165d71ae5a4SJacob Faibussowitsch { 5166aa50250dSMatthew G. Knepley PetscFunctionBegin; 5167aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 51684f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5169c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 51703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5171aa50250dSMatthew G. Knepley } 5172aa50250dSMatthew G. Knepley 5173aa50250dSMatthew G. Knepley /*@ 5174aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5175aa50250dSMatthew G. Knepley 5176aa50250dSMatthew G. Knepley Not Collective 5177aa50250dSMatthew G. Knepley 5178aa50250dSMatthew G. Knepley Input Parameter: 5179a1cb98faSBarry Smith . dm - The `DMPLEX` object 5180aa50250dSMatthew G. Knepley 5181aa50250dSMatthew G. Knepley Output Parameter: 5182aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5183aa50250dSMatthew G. Knepley 5184aa50250dSMatthew G. Knepley Level: developer 5185552f7358SJed Brown 5186b1bb481bSMatthew Knepley Notes: 5187a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5188a1cb98faSBarry Smith 5189a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5190a1cb98faSBarry Smith 5191dc287ab2SVaclav Hapla An empty mesh gives -1. 5192b1bb481bSMatthew Knepley 51931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5194552f7358SJed Brown @*/ 5195d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5196d71ae5a4SJacob Faibussowitsch { 51979f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5198aa50250dSMatthew G. Knepley DMLabel label; 5199aa50250dSMatthew G. Knepley PetscInt d = 0; 5200552f7358SJed Brown 5201552f7358SJed Brown PetscFunctionBegin; 5202552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52034f572ea9SToby Isaac PetscAssertPointer(depth, 2); 52049f4ada15SMatthew G. Knepley if (mesh->tr) { 52059f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 52069f4ada15SMatthew G. Knepley } else { 52079566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 52089566063dSJacob Faibussowitsch if (label) PetscCall(DMLabelGetNumValues(label, &d)); 5209552f7358SJed Brown *depth = d - 1; 52109f4ada15SMatthew G. Knepley } 52113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5212552f7358SJed Brown } 5213552f7358SJed Brown 5214552f7358SJed Brown /*@ 521520f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5216552f7358SJed Brown 5217552f7358SJed Brown Not Collective 5218552f7358SJed Brown 5219552f7358SJed Brown Input Parameters: 5220a1cb98faSBarry Smith + dm - The `DMPLEX` object 5221570fa34dSVaclav Hapla - depth - The requested depth 5222552f7358SJed Brown 5223552f7358SJed Brown Output Parameters: 522420f4b53cSBarry Smith + start - The first point at this `depth` 522520f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5226552f7358SJed Brown 5227552f7358SJed Brown Level: developer 5228552f7358SJed Brown 5229a1cb98faSBarry Smith Notes: 5230a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5231a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5232a1cb98faSBarry Smith higher dimension, e.g., "edges". 5233a1cb98faSBarry Smith 52342827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5235552f7358SJed Brown @*/ 5236d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5237d71ae5a4SJacob Faibussowitsch { 52389f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5239aa50250dSMatthew G. Knepley DMLabel label; 524063d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5241552f7358SJed Brown 5242552f7358SJed Brown PetscFunctionBegin; 5243552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52449371c9d4SSatish Balay if (start) { 52454f572ea9SToby Isaac PetscAssertPointer(start, 3); 52469371c9d4SSatish Balay *start = 0; 52479371c9d4SSatish Balay } 52489371c9d4SSatish Balay if (end) { 52494f572ea9SToby Isaac PetscAssertPointer(end, 4); 52509371c9d4SSatish Balay *end = 0; 52519371c9d4SSatish Balay } 52529566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 52533ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5254570fa34dSVaclav Hapla if (depth < 0) { 525563d1a920SMatthew G. Knepley if (start) *start = pStart; 525663d1a920SMatthew G. Knepley if (end) *end = pEnd; 52573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5258552f7358SJed Brown } 52599f4ada15SMatthew G. Knepley if (mesh->tr) { 52609f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 52619f4ada15SMatthew G. Knepley } else { 52629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 526328b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5264570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 52659f4ada15SMatthew G. Knepley } 52663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5267552f7358SJed Brown } 5268552f7358SJed Brown 5269552f7358SJed Brown /*@ 527020f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5271552f7358SJed Brown 5272552f7358SJed Brown Not Collective 5273552f7358SJed Brown 5274552f7358SJed Brown Input Parameters: 5275a1cb98faSBarry Smith + dm - The `DMPLEX` object 5276570fa34dSVaclav Hapla - height - The requested height 5277552f7358SJed Brown 5278552f7358SJed Brown Output Parameters: 527920f4b53cSBarry Smith + start - The first point at this `height` 528020f4b53cSBarry Smith - end - One beyond the last point at this `height` 5281552f7358SJed Brown 5282552f7358SJed Brown Level: developer 5283552f7358SJed Brown 5284a1cb98faSBarry Smith Notes: 5285a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5286a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5287a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5288a1cb98faSBarry Smith 52892827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5290552f7358SJed Brown @*/ 5291d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5292d71ae5a4SJacob Faibussowitsch { 5293aa50250dSMatthew G. Knepley DMLabel label; 529463d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5295552f7358SJed Brown 5296552f7358SJed Brown PetscFunctionBegin; 5297552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 52989371c9d4SSatish Balay if (start) { 52994f572ea9SToby Isaac PetscAssertPointer(start, 3); 53009371c9d4SSatish Balay *start = 0; 53019371c9d4SSatish Balay } 53029371c9d4SSatish Balay if (end) { 53034f572ea9SToby Isaac PetscAssertPointer(end, 4); 53049371c9d4SSatish Balay *end = 0; 53059371c9d4SSatish Balay } 53069566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 53073ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5308570fa34dSVaclav Hapla if (height < 0) { 530963d1a920SMatthew G. Knepley if (start) *start = pStart; 531063d1a920SMatthew G. Knepley if (end) *end = pEnd; 53113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5312552f7358SJed Brown } 53139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 531459e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 531559e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 531659e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 531759e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 53183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5319552f7358SJed Brown } 5320552f7358SJed Brown 5321ba2698f1SMatthew G. Knepley /*@ 532220f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5323ba2698f1SMatthew G. Knepley 5324ba2698f1SMatthew G. Knepley Not Collective 5325ba2698f1SMatthew G. Knepley 5326d8d19677SJose E. Roman Input Parameters: 5327a1cb98faSBarry Smith + dm - The `DMPLEX` object 5328ba2698f1SMatthew G. Knepley - point - The point 5329ba2698f1SMatthew G. Knepley 5330ba2698f1SMatthew G. Knepley Output Parameter: 533120f4b53cSBarry Smith . depth - The depth of the `point` 5332ba2698f1SMatthew G. Knepley 5333ba2698f1SMatthew G. Knepley Level: intermediate 5334ba2698f1SMatthew G. Knepley 53351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5336ba2698f1SMatthew G. Knepley @*/ 5337d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5338d71ae5a4SJacob Faibussowitsch { 5339ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5340ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53414f572ea9SToby Isaac PetscAssertPointer(depth, 3); 53429566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 53433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5344ba2698f1SMatthew G. Knepley } 5345ba2698f1SMatthew G. Knepley 5346ba2698f1SMatthew G. Knepley /*@ 534720f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 53480c0a32dcSVaclav Hapla 53490c0a32dcSVaclav Hapla Not Collective 53500c0a32dcSVaclav Hapla 5351d8d19677SJose E. Roman Input Parameters: 5352a1cb98faSBarry Smith + dm - The `DMPLEX` object 53530c0a32dcSVaclav Hapla - point - The point 53540c0a32dcSVaclav Hapla 53550c0a32dcSVaclav Hapla Output Parameter: 535620f4b53cSBarry Smith . height - The height of the `point` 53570c0a32dcSVaclav Hapla 53580c0a32dcSVaclav Hapla Level: intermediate 53590c0a32dcSVaclav Hapla 53601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 53610c0a32dcSVaclav Hapla @*/ 5362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5363d71ae5a4SJacob Faibussowitsch { 53640c0a32dcSVaclav Hapla PetscInt n, pDepth; 53650c0a32dcSVaclav Hapla 53660c0a32dcSVaclav Hapla PetscFunctionBegin; 53670c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53684f572ea9SToby Isaac PetscAssertPointer(height, 3); 53699566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 53709566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 53710c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 53723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53730c0a32dcSVaclav Hapla } 53740c0a32dcSVaclav Hapla 53750c0a32dcSVaclav Hapla /*@ 5376a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5377ba2698f1SMatthew G. Knepley 5378ba2698f1SMatthew G. Knepley Not Collective 5379ba2698f1SMatthew G. Knepley 5380ba2698f1SMatthew G. Knepley Input Parameter: 5381a1cb98faSBarry Smith . dm - The `DMPLEX` object 5382ba2698f1SMatthew G. Knepley 5383ba2698f1SMatthew G. Knepley Output Parameter: 5384a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5385412e9a14SMatthew G. Knepley 5386ba2698f1SMatthew G. Knepley Level: developer 5387ba2698f1SMatthew G. Knepley 5388a1cb98faSBarry Smith Note: 5389a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5390a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5391a1cb98faSBarry Smith 53921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5393ba2698f1SMatthew G. Knepley @*/ 5394d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5395d71ae5a4SJacob Faibussowitsch { 5396ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5397ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53984f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 53999566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5400ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 54013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5402ba2698f1SMatthew G. Knepley } 5403ba2698f1SMatthew G. Knepley 5404ba2698f1SMatthew G. Knepley /*@ 5405ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5406ba2698f1SMatthew G. Knepley 5407ba2698f1SMatthew G. Knepley Not Collective 5408ba2698f1SMatthew G. Knepley 5409d8d19677SJose E. Roman Input Parameters: 5410a1cb98faSBarry Smith + dm - The `DMPLEX` object 5411ba2698f1SMatthew G. Knepley - cell - The cell 5412ba2698f1SMatthew G. Knepley 5413ba2698f1SMatthew G. Knepley Output Parameter: 5414ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5415ba2698f1SMatthew G. Knepley 5416ba2698f1SMatthew G. Knepley Level: intermediate 5417ba2698f1SMatthew G. Knepley 54181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5419ba2698f1SMatthew G. Knepley @*/ 5420d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5421d71ae5a4SJacob Faibussowitsch { 54229f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5423ba2698f1SMatthew G. Knepley DMLabel label; 5424ba2698f1SMatthew G. Knepley PetscInt ct; 5425ba2698f1SMatthew G. Knepley 5426ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5427ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54284f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 54299f4ada15SMatthew G. Knepley if (mesh->tr) { 54309f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 54319f4ada15SMatthew G. Knepley } else { 543221027e53SStefano Zampini PetscInt pStart, pEnd; 543321027e53SStefano Zampini 543421027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 543521027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 543621027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 543721027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 543821027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 543921027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 544021027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 544121027e53SStefano Zampini mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct; 544221027e53SStefano Zampini } 544321027e53SStefano Zampini } 544421027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 544521027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 54469566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 544863a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5449936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 545021027e53SStefano Zampini } 54519f4ada15SMatthew G. Knepley } 54523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5453ba2698f1SMatthew G. Knepley } 5454ba2698f1SMatthew G. Knepley 5455412e9a14SMatthew G. Knepley /*@ 5456412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5457412e9a14SMatthew G. Knepley 5458412e9a14SMatthew G. Knepley Not Collective 5459412e9a14SMatthew G. Knepley 5460412e9a14SMatthew G. Knepley Input Parameters: 5461a1cb98faSBarry Smith + dm - The `DMPLEX` object 5462412e9a14SMatthew G. Knepley . cell - The cell 5463412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5464412e9a14SMatthew G. Knepley 5465a1cb98faSBarry Smith Level: advanced 5466a1cb98faSBarry Smith 5467a1cb98faSBarry Smith Note: 5468a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5469412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5470412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5471db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5472412e9a14SMatthew G. Knepley 54731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5474412e9a14SMatthew G. Knepley @*/ 5475d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5476d71ae5a4SJacob Faibussowitsch { 547721027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5478412e9a14SMatthew G. Knepley DMLabel label; 547921027e53SStefano Zampini PetscInt pStart, pEnd; 5480412e9a14SMatthew G. Knepley 5481412e9a14SMatthew G. Knepley PetscFunctionBegin; 5482412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 548321027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 54849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 54859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 548621027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 548721027e53SStefano Zampini mesh->cellTypes[cell - pStart].value_as_uint8 = celltype; 54883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5489412e9a14SMatthew G. Knepley } 5490412e9a14SMatthew G. Knepley 5491d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5492d71ae5a4SJacob Faibussowitsch { 5493efe440bfSMatthew G. Knepley PetscSection section, s; 5494efe440bfSMatthew G. Knepley Mat m; 54953e922f36SToby Isaac PetscInt maxHeight; 5496dd4c3f67SMatthew G. Knepley const char *prefix; 5497552f7358SJed Brown 5498552f7358SJed Brown PetscFunctionBegin; 54999566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5500dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5501dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5502dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 55039566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 55049566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 55059566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 55069566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 55079566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 55089566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s)); 55099566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &m)); 55109566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL)); 55119566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&s)); 55129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&m)); 55138f4c458bSMatthew G. Knepley 55149566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 55159566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5516dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5517dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 55183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5519552f7358SJed Brown } 5520552f7358SJed Brown 5521d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5522d71ae5a4SJacob Faibussowitsch { 55236858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 55246858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5525f19dbd58SToby Isaac 5526f19dbd58SToby Isaac PetscFunctionBegin; 5527f19dbd58SToby Isaac *field = NULL; 55289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 55299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 55306858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 55316858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5532f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 55336858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 55346858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5535f19dbd58SToby Isaac } 55363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5537f19dbd58SToby Isaac } 5538f19dbd58SToby Isaac 55397cd05799SMatthew G. Knepley /*@C 55407cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 55417cd05799SMatthew G. Knepley 55427cd05799SMatthew G. Knepley Not Collective 55437cd05799SMatthew G. Knepley 55442fe279fdSBarry Smith Input Parameter: 5545a1cb98faSBarry Smith . dm - The `DMPLEX` object 55467cd05799SMatthew G. Knepley 55477cd05799SMatthew G. Knepley Output Parameter: 5548a1cb98faSBarry Smith . section - The `PetscSection` object 55497cd05799SMatthew G. Knepley 55507cd05799SMatthew G. Knepley Level: developer 55517cd05799SMatthew G. Knepley 55521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 55537cd05799SMatthew G. Knepley @*/ 5554d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5555d71ae5a4SJacob Faibussowitsch { 5556552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5557552f7358SJed Brown 5558552f7358SJed Brown PetscFunctionBegin; 5559552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5560552f7358SJed Brown if (section) *section = mesh->coneSection; 55613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5562552f7358SJed Brown } 5563552f7358SJed Brown 55647cd05799SMatthew G. Knepley /*@C 55657cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 55667cd05799SMatthew G. Knepley 55677cd05799SMatthew G. Knepley Not Collective 55687cd05799SMatthew G. Knepley 55692fe279fdSBarry Smith Input Parameter: 5570a1cb98faSBarry Smith . dm - The `DMPLEX` object 55717cd05799SMatthew G. Knepley 55727cd05799SMatthew G. Knepley Output Parameter: 5573a1cb98faSBarry Smith . section - The `PetscSection` object 55747cd05799SMatthew G. Knepley 55757cd05799SMatthew G. Knepley Level: developer 55767cd05799SMatthew G. Knepley 55771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 55787cd05799SMatthew G. Knepley @*/ 5579d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5580d71ae5a4SJacob Faibussowitsch { 55818cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 55828cb4d582SMatthew G. Knepley 55838cb4d582SMatthew G. Knepley PetscFunctionBegin; 55848cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55858cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 55863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55878cb4d582SMatthew G. Knepley } 55888cb4d582SMatthew G. Knepley 55897cd05799SMatthew G. Knepley /*@C 55907cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 55917cd05799SMatthew G. Knepley 55927cd05799SMatthew G. Knepley Not Collective 55937cd05799SMatthew G. Knepley 55942fe279fdSBarry Smith Input Parameter: 5595a1cb98faSBarry Smith . dm - The `DMPLEX` object 55967cd05799SMatthew G. Knepley 55977cd05799SMatthew G. Knepley Output Parameter: 55987cd05799SMatthew G. Knepley . cones - The cone for each point 55997cd05799SMatthew G. Knepley 56007cd05799SMatthew G. Knepley Level: developer 56017cd05799SMatthew G. Knepley 56021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 56037cd05799SMatthew G. Knepley @*/ 5604d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5605d71ae5a4SJacob Faibussowitsch { 5606552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5607552f7358SJed Brown 5608552f7358SJed Brown PetscFunctionBegin; 5609552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5610552f7358SJed Brown if (cones) *cones = mesh->cones; 56113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5612552f7358SJed Brown } 5613552f7358SJed Brown 56147cd05799SMatthew G. Knepley /*@C 56157cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 56167cd05799SMatthew G. Knepley 56177cd05799SMatthew G. Knepley Not Collective 56187cd05799SMatthew G. Knepley 56192fe279fdSBarry Smith Input Parameter: 5620a1cb98faSBarry Smith . dm - The `DMPLEX` object 56217cd05799SMatthew G. Knepley 56227cd05799SMatthew G. Knepley Output Parameter: 5623b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 56247cd05799SMatthew G. Knepley 56257cd05799SMatthew G. Knepley Level: developer 56267cd05799SMatthew G. Knepley 5627b5a892a1SMatthew G. Knepley Notes: 5628a1cb98faSBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`. 5629b5a892a1SMatthew G. Knepley 5630a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5631b5a892a1SMatthew G. Knepley 56321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 56337cd05799SMatthew G. Knepley @*/ 5634d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5635d71ae5a4SJacob Faibussowitsch { 5636552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5637552f7358SJed Brown 5638552f7358SJed Brown PetscFunctionBegin; 5639552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5640552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 56413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5642552f7358SJed Brown } 5643552f7358SJed Brown 5644552f7358SJed Brown /******************************** FEM Support **********************************/ 5645552f7358SJed Brown 5646d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5647d2b2dc1eSMatthew G. Knepley { 5648d2b2dc1eSMatthew G. Knepley PetscInt depth; 5649d2b2dc1eSMatthew G. Knepley 5650d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5651d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5652d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5653d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5654d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5655d2b2dc1eSMatthew G. Knepley } 5656d2b2dc1eSMatthew G. Knepley 56575962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 56585962854dSMatthew G. Knepley { 56595962854dSMatthew G. Knepley PetscInt depth; 56605962854dSMatthew G. Knepley 56615962854dSMatthew G. Knepley PetscFunctionBegin; 56625962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 56635962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 56645962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 56655962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 56665962854dSMatthew G. Knepley } 56675962854dSMatthew G. Knepley 56689e8305c2SJed Brown /* 56699e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 56709e8305c2SJed Brown representing a line in the section. 56719e8305c2SJed Brown */ 5672e327e467SRezgar Shakeri static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous) 5673d71ae5a4SJacob Faibussowitsch { 5674e327e467SRezgar Shakeri PetscObject obj; 5675e327e467SRezgar Shakeri PetscClassId id; 5676e327e467SRezgar Shakeri PetscFE fe = NULL; 5677e327e467SRezgar Shakeri 56789e8305c2SJed Brown PetscFunctionBeginHot; 56799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5680e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5681e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5682e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5683e327e467SRezgar Shakeri 5684e327e467SRezgar Shakeri if (!fe) { 5685e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 56869e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 56879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 56889e8305c2SJed Brown *k = *k / *Nc + 1; 5689e327e467SRezgar Shakeri } else { 5690e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 5691e327e467SRezgar Shakeri PetscDualSpace dual_space; 5692e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 5693e327e467SRezgar Shakeri PetscCall(PetscFEGetDualSpace(fe, &dual_space)); 5694e327e467SRezgar Shakeri PetscCall(PetscDualSpaceGetDimension(dual_space, &dual_space_size)); 5695e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 5696e327e467SRezgar Shakeri PetscCall(PetscDualSpaceLagrangeGetContinuity(dual_space, continuous)); 56979e8305c2SJed Brown } 56983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56999e8305c2SJed Brown } 57009e8305c2SJed Brown 5701a4355906SMatthew Knepley /*@ 5702bc1eb3faSJed Brown 5703bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5704bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 570520f4b53cSBarry Smith section provided (or the section of the `DM`). 5706a4355906SMatthew Knepley 5707a4355906SMatthew Knepley Input Parameters: 570820f4b53cSBarry Smith + dm - The `DM` 570920f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 571020f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5711a4355906SMatthew Knepley 5712bc1eb3faSJed Brown Example: 5713bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5714bc1eb3faSJed Brown .vb 5715bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5716bc1eb3faSJed Brown 5717bc1eb3faSJed Brown v4 -- e6 -- v3 5718bc1eb3faSJed Brown | | 5719bc1eb3faSJed Brown e7 c0 e8 5720bc1eb3faSJed Brown | | 5721bc1eb3faSJed Brown v1 -- e5 -- v2 5722bc1eb3faSJed Brown .ve 5723bc1eb3faSJed Brown 5724bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5725bc1eb3faSJed Brown dofs in the order of points, e.g., 5726bc1eb3faSJed Brown .vb 5727bc1eb3faSJed Brown c0 -> [0,1,2,3] 5728bc1eb3faSJed Brown v1 -> [4] 5729bc1eb3faSJed Brown ... 5730bc1eb3faSJed Brown e5 -> [8, 9] 5731bc1eb3faSJed Brown .ve 5732bc1eb3faSJed Brown 5733bc1eb3faSJed Brown which corresponds to the dofs 5734bc1eb3faSJed Brown .vb 5735bc1eb3faSJed Brown 6 10 11 7 5736bc1eb3faSJed Brown 13 2 3 15 5737bc1eb3faSJed Brown 12 0 1 14 5738bc1eb3faSJed Brown 4 8 9 5 5739bc1eb3faSJed Brown .ve 5740bc1eb3faSJed Brown 5741bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5742bc1eb3faSJed Brown .vb 5743bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5744bc1eb3faSJed Brown .ve 5745bc1eb3faSJed Brown 5746bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5747bc1eb3faSJed Brown .vb 5748bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5749bc1eb3faSJed Brown .ve 5750bc1eb3faSJed Brown 5751a4355906SMatthew Knepley Level: developer 5752a4355906SMatthew Knepley 5753da9ac489SAlbert Cowie Notes: 5754a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5755a1cb98faSBarry Smith degree of the basis. 5756a1cb98faSBarry Smith 5757da9ac489SAlbert Cowie This is required to run with libCEED. 5758da9ac489SAlbert Cowie 57591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5760a4355906SMatthew Knepley @*/ 5761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5762d71ae5a4SJacob Faibussowitsch { 57637391a63aSMatthew G. Knepley DMLabel label; 5764bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 5765e327e467SRezgar Shakeri PetscBool continuous = PETSC_TRUE; 57663194fc30SMatthew G. Knepley 57673194fc30SMatthew G. Knepley PetscFunctionBegin; 57689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 57693ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5770a433471fSStefano Zampini if (point < 0) { 5771a433471fSStefano Zampini PetscInt sStart, sEnd; 5772a433471fSStefano Zampini 57739566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5774a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5775a433471fSStefano Zampini } 57769566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 57779566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 57789566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 57799371c9d4SSatish Balay if (depth == 1) { 57809371c9d4SSatish Balay eStart = point; 57819371c9d4SSatish Balay } else if (depth == dim) { 57827391a63aSMatthew G. Knepley const PetscInt *cone; 57837391a63aSMatthew G. Knepley 57849566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5785d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5786d4e6627bSStefano Zampini else if (dim == 3) { 5787d4e6627bSStefano Zampini const PetscInt *cone2; 57889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5789d4e6627bSStefano Zampini eStart = cone2[0]; 579063a3b9bcSJacob 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); 579163a3b9bcSJacob 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); 5792e327e467SRezgar Shakeri 57939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5794bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5795bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5796bb197d40SJed Brown PetscInt *perm; 5797bb197d40SJed Brown 57983194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5799e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 5800bb197d40SJed Brown size += PetscPowInt(k + 1, d) * Nc; 58013194fc30SMatthew G. Knepley } 58029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 58033194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5804bb197d40SJed Brown switch (d) { 5805babf31e0SJed Brown case 1: 5806e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 5807babf31e0SJed Brown /* 5808babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5809babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5810babf31e0SJed Brown */ 5811e327e467SRezgar Shakeri if (continuous) { 5812babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 58139371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 58149371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5815babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5816babf31e0SJed Brown foffset = offset; 5817e327e467SRezgar Shakeri } else { 5818e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5819e327e467SRezgar Shakeri foffset = offset = size; 5820e327e467SRezgar Shakeri } 5821babf31e0SJed Brown break; 582289eabcffSMatthew G. Knepley case 2: 58233194fc30SMatthew 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} */ 5824e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 58253194fc30SMatthew G. Knepley /* The SEM order is 58263194fc30SMatthew G. Knepley 58273194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 582889eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 58293194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 58303194fc30SMatthew G. Knepley */ 5831e327e467SRezgar Shakeri if (continuous) { 58323194fc30SMatthew G. Knepley const PetscInt of = 0; 58333194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 58343194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 58353194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 58363194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 58373194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 58383194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 58393194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 58403194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 58413194fc30SMatthew G. Knepley PetscInt o; 58423194fc30SMatthew G. Knepley 58433194fc30SMatthew G. Knepley /* bottom */ 58443194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 58459371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 58469371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 58473194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 58483194fc30SMatthew G. Knepley /* middle */ 58493194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 58503194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 58519371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 58529371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 58533194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 58543194fc30SMatthew G. Knepley } 58553194fc30SMatthew G. Knepley /* top */ 58563194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 58579371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 58589371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 58593194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 58603194fc30SMatthew G. Knepley foffset = offset; 5861e327e467SRezgar Shakeri } else { 5862e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5863e327e467SRezgar Shakeri foffset = offset = size; 58643194fc30SMatthew G. Knepley } 586589eabcffSMatthew G. Knepley break; 586689eabcffSMatthew G. Knepley case 3: 586789eabcffSMatthew G. Knepley /* The original hex closure is 586889eabcffSMatthew G. Knepley 586989eabcffSMatthew G. Knepley {c, 587089eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 587189eabcffSMatthew 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, 587289eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 587389eabcffSMatthew G. Knepley */ 5874e327e467SRezgar Shakeri PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous)); 587589eabcffSMatthew G. Knepley /* The SEM order is 587689eabcffSMatthew G. Knepley Bottom Slice 587789eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 587889eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 587989eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 588089eabcffSMatthew G. Knepley 588189eabcffSMatthew G. Knepley Middle Slice (j) 588289eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 588389eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 588489eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 588589eabcffSMatthew G. Knepley 588689eabcffSMatthew G. Knepley Top Slice 588789eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 588889eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 588989eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 589089eabcffSMatthew G. Knepley */ 5891e327e467SRezgar Shakeri if (continuous) { 589289eabcffSMatthew G. Knepley const PetscInt oc = 0; 589389eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 589489eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 589589eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 589689eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 589789eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 589889eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 589989eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 590089eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 590189eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 590289eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 590389eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 590489eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 590589eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 590689eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 590789eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 590889eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 590989eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 591089eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 591189eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 591289eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 591389eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 591489eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 591589eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 591689eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 591789eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 591889eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 591989eabcffSMatthew G. Knepley PetscInt o, n; 592089eabcffSMatthew G. Knepley 592189eabcffSMatthew G. Knepley /* Bottom Slice */ 592289eabcffSMatthew G. Knepley /* bottom */ 592389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 59249371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 59259371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 592689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 592789eabcffSMatthew G. Knepley /* middle */ 592889eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 592989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 59309371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 59319371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 59329371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 59339371c9d4SSatish Balay } 593489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 59353194fc30SMatthew G. Knepley } 593689eabcffSMatthew G. Knepley /* top */ 593789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 59389371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 59399371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 594089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 594189eabcffSMatthew G. Knepley 594289eabcffSMatthew G. Knepley /* Middle Slice */ 594389eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 594489eabcffSMatthew G. Knepley /* bottom */ 594589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 59469371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 59479371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 594889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 594989eabcffSMatthew G. Knepley /* middle */ 595089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 595189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 59529371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 59539371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 595489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 595589eabcffSMatthew G. Knepley } 595689eabcffSMatthew G. Knepley /* top */ 595789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 59589371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 59599371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 596089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 596189eabcffSMatthew G. Knepley } 596289eabcffSMatthew G. Knepley 596389eabcffSMatthew G. Knepley /* Top Slice */ 596489eabcffSMatthew G. Knepley /* bottom */ 596589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 59669371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 59679371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 596889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 596989eabcffSMatthew G. Knepley /* middle */ 597089eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 597189eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 59729371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 59739371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 597489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 597589eabcffSMatthew G. Knepley } 597689eabcffSMatthew G. Knepley /* top */ 597789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 59789371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 59799371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 598089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 598189eabcffSMatthew G. Knepley 598289eabcffSMatthew G. Knepley foffset = offset; 5983e327e467SRezgar Shakeri } else { 5984e327e467SRezgar Shakeri for (i = offset; i < size; i++) perm[i] = i - offset + foffset; 5985e327e467SRezgar Shakeri foffset = offset = size; 598689eabcffSMatthew G. Knepley } 598789eabcffSMatthew G. Knepley break; 5988d71ae5a4SJacob Faibussowitsch default: 5989d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 599089eabcffSMatthew G. Knepley } 599189eabcffSMatthew G. Knepley } 599263a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 59933194fc30SMatthew G. Knepley /* Check permutation */ 59943194fc30SMatthew G. Knepley { 59953194fc30SMatthew G. Knepley PetscInt *check; 59963194fc30SMatthew G. Knepley 59979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 59981dca8a05SBarry Smith for (i = 0; i < size; ++i) { 59991dca8a05SBarry Smith check[i] = -1; 60001dca8a05SBarry 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]); 60011dca8a05SBarry Smith } 60023194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 60031dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 60049566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 60053194fc30SMatthew G. Knepley } 60069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6007a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6008a05c9aa3SJed Brown PetscInt *loc_perm; 60099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6010a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6011a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6012a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6013a05c9aa3SJed Brown } 60149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6015a05c9aa3SJed Brown } 6016bb197d40SJed Brown } 60173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60183194fc30SMatthew G. Knepley } 60193194fc30SMatthew G. Knepley 6020d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6021d71ae5a4SJacob Faibussowitsch { 6022e071409bSToby Isaac PetscDS prob; 6023e071409bSToby Isaac PetscInt depth, Nf, h; 6024e071409bSToby Isaac DMLabel label; 6025e071409bSToby Isaac 6026e071409bSToby Isaac PetscFunctionBeginHot; 60279566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6028e071409bSToby Isaac Nf = prob->Nf; 6029e071409bSToby Isaac label = dm->depthLabel; 6030e071409bSToby Isaac *dspace = NULL; 6031e071409bSToby Isaac if (field < Nf) { 6032e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6033e071409bSToby Isaac 6034e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6035e071409bSToby Isaac PetscDualSpace dsp; 6036e071409bSToby Isaac 60379566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 60389566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 60399566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6040e071409bSToby Isaac h = depth - 1 - h; 6041e071409bSToby Isaac if (h) { 60429566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6043e071409bSToby Isaac } else { 6044e071409bSToby Isaac *dspace = dsp; 6045e071409bSToby Isaac } 6046e071409bSToby Isaac } 6047e071409bSToby Isaac } 60483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6049e071409bSToby Isaac } 6050e071409bSToby Isaac 6051d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6052d71ae5a4SJacob Faibussowitsch { 605328351e22SJed Brown PetscScalar *array; 605428351e22SJed Brown const PetscScalar *vArray; 6055d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 60561a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6057552f7358SJed Brown 60581b406b76SMatthew G. Knepley PetscFunctionBeginHot; 60599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 60609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 60619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 60629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 60633f7cbbe7SMatthew G. Knepley if (!values || !*values) { 60649df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 60659df71ca4SMatthew G. Knepley PetscInt dof; 6066d9917b9dSMatthew G. Knepley 60679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 60689df71ca4SMatthew G. Knepley size += dof; 60699df71ca4SMatthew G. Knepley } 60709df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 60719df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 60722a3aaacfSMatthew G. Knepley PetscInt dof; 60735a1bb5cfSMatthew G. Knepley 60745a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 60759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 60765a1bb5cfSMatthew G. Knepley size += dof; 60775a1bb5cfSMatthew G. Knepley } 60783f7cbbe7SMatthew G. Knepley if (!values) { 60793f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 60803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 60813f7cbbe7SMatthew G. Knepley } 60829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6083982e9ed1SMatthew G. Knepley } else { 6084982e9ed1SMatthew G. Knepley array = *values; 6085982e9ed1SMatthew G. Knepley } 60869df71ca4SMatthew G. Knepley size = 0; 608728351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 60889df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 60899df71ca4SMatthew G. Knepley PetscInt dof, off, d; 609028351e22SJed Brown const PetscScalar *varr; 6091d9917b9dSMatthew G. Knepley 60929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 60939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 60949df71ca4SMatthew G. Knepley varr = &vArray[off]; 6095ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 60969df71ca4SMatthew G. Knepley size += dof; 60979df71ca4SMatthew G. Knepley } 60989df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 60999df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 61009df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 61015a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 610228351e22SJed Brown const PetscScalar *varr; 61035a1bb5cfSMatthew G. Knepley 610452ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 61059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 61069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 61075a1bb5cfSMatthew G. Knepley varr = &vArray[off]; 61085a1bb5cfSMatthew G. Knepley if (o >= 0) { 6109ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 61105a1bb5cfSMatthew G. Knepley } else { 6111ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 61125a1bb5cfSMatthew G. Knepley } 61139df71ca4SMatthew G. Knepley size += dof; 61145a1bb5cfSMatthew G. Knepley } 611528351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 61169df71ca4SMatthew G. Knepley if (!*values) { 61175a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 61185a1bb5cfSMatthew G. Knepley *values = array; 61199df71ca4SMatthew G. Knepley } else { 612063a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 61218c312ff3SMatthew G. Knepley *csize = size; 61229df71ca4SMatthew G. Knepley } 61233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 61245a1bb5cfSMatthew G. Knepley } 6125d9917b9dSMatthew G. Knepley 612627f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6127d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6128d71ae5a4SJacob Faibussowitsch { 612927f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 613027f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 613127f02ce8SMatthew G. Knepley 61329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 613327f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 613427f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 613527f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 613627f02ce8SMatthew G. Knepley points[q * 2] = r; 613727f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 613827f02ce8SMatthew G. Knepley ++q; 613927f02ce8SMatthew G. Knepley } 614027f02ce8SMatthew G. Knepley } 614127f02ce8SMatthew G. Knepley *numPoints = q; 61423ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 614327f02ce8SMatthew G. Knepley } 614427f02ce8SMatthew G. Knepley 614597529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 614607218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6147d71ae5a4SJacob Faibussowitsch { 614827f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6149923c78e0SToby Isaac PetscInt np, *pts = NULL; 6150923c78e0SToby Isaac 6151923c78e0SToby Isaac PetscFunctionBeginHot; 61529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 615307218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6154923c78e0SToby Isaac PetscInt dof, off; 6155923c78e0SToby Isaac 61569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 61579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 61589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6159923c78e0SToby Isaac np = dof / 2; 6160923c78e0SToby Isaac pts = (PetscInt *)&cla[off]; 616127f02ce8SMatthew G. Knepley } else { 616207218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 61639566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6164923c78e0SToby Isaac } 6165923c78e0SToby Isaac *numPoints = np; 6166923c78e0SToby Isaac *points = pts; 6167923c78e0SToby Isaac *clp = cla; 61683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6169923c78e0SToby Isaac } 6170923c78e0SToby Isaac 6171d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6172d71ae5a4SJacob Faibussowitsch { 6173923c78e0SToby Isaac PetscFunctionBeginHot; 6174923c78e0SToby Isaac if (!*clPoints) { 61759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6176923c78e0SToby Isaac } else { 61779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6178923c78e0SToby Isaac } 6179923c78e0SToby Isaac *numPoints = 0; 6180923c78e0SToby Isaac *points = NULL; 6181923c78e0SToby Isaac *clSec = NULL; 6182923c78e0SToby Isaac *clPoints = NULL; 6183923c78e0SToby Isaac *clp = NULL; 61843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6185923c78e0SToby Isaac } 6186923c78e0SToby Isaac 6187d71ae5a4SJacob 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[]) 6188d71ae5a4SJacob Faibussowitsch { 61891a271a75SMatthew G. Knepley PetscInt offset = 0, p; 619097e99dd9SToby Isaac const PetscInt **perms = NULL; 619197e99dd9SToby Isaac const PetscScalar **flips = NULL; 61921a271a75SMatthew G. Knepley 61931a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6194fe02ba77SJed Brown *size = 0; 61959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 619697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 619797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 619897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 619997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62001a271a75SMatthew G. Knepley PetscInt dof, off, d; 62011a271a75SMatthew G. Knepley const PetscScalar *varr; 62021a271a75SMatthew G. Knepley 62039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62051a271a75SMatthew G. Knepley varr = &vArray[off]; 620697e99dd9SToby Isaac if (clperm) { 620797e99dd9SToby Isaac if (perm) { 620897e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 62091a271a75SMatthew G. Knepley } else { 621097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 621197e99dd9SToby Isaac } 621297e99dd9SToby Isaac if (flip) { 621397e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 621497e99dd9SToby Isaac } 621597e99dd9SToby Isaac } else { 621697e99dd9SToby Isaac if (perm) { 621797e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 621897e99dd9SToby Isaac } else { 621997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 622097e99dd9SToby Isaac } 622197e99dd9SToby Isaac if (flip) { 622297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 62231a271a75SMatthew G. Knepley } 62241a271a75SMatthew G. Knepley } 622597e99dd9SToby Isaac offset += dof; 622697e99dd9SToby Isaac } 62279566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 62281a271a75SMatthew G. Knepley *size = offset; 62293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62301a271a75SMatthew G. Knepley } 62311a271a75SMatthew G. Knepley 6232d71ae5a4SJacob 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[]) 6233d71ae5a4SJacob Faibussowitsch { 62341a271a75SMatthew G. Knepley PetscInt offset = 0, f; 62351a271a75SMatthew G. Knepley 62361a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6237fe02ba77SJed Brown *size = 0; 62381a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 623997e99dd9SToby Isaac PetscInt p; 624097e99dd9SToby Isaac const PetscInt **perms = NULL; 624197e99dd9SToby Isaac const PetscScalar **flips = NULL; 62421a271a75SMatthew G. Knepley 62439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 624497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 624597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 624697e99dd9SToby Isaac PetscInt fdof, foff, b; 62471a271a75SMatthew G. Knepley const PetscScalar *varr; 624897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 624997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 62501a271a75SMatthew G. Knepley 62519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 62529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 62531a271a75SMatthew G. Knepley varr = &vArray[foff]; 625497e99dd9SToby Isaac if (clperm) { 62559371c9d4SSatish Balay if (perm) { 6256ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 62571a271a75SMatthew G. Knepley } else { 6258ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 62599371c9d4SSatish Balay } 62609371c9d4SSatish Balay if (flip) { 6261ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 62629371c9d4SSatish Balay } 62639371c9d4SSatish Balay } else { 62649371c9d4SSatish Balay if (perm) { 6265ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 62669371c9d4SSatish Balay } else { 6267ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 62689371c9d4SSatish Balay } 62699371c9d4SSatish Balay if (flip) { 6270ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 62719371c9d4SSatish Balay } 62721a271a75SMatthew G. Knepley } 627397e99dd9SToby Isaac offset += fdof; 62741a271a75SMatthew G. Knepley } 62759566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 62761a271a75SMatthew G. Knepley } 62771a271a75SMatthew G. Knepley *size = offset; 62783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62791a271a75SMatthew G. Knepley } 62801a271a75SMatthew G. Knepley 6281e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 628207218a29SMatthew G. Knepley { 628307218a29SMatthew G. Knepley PetscSection clSection; 628407218a29SMatthew G. Knepley IS clPoints; 628507218a29SMatthew G. Knepley PetscInt *points = NULL; 6286e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 628707218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 628807218a29SMatthew G. Knepley 628907218a29SMatthew G. Knepley PetscFunctionBeginHot; 629007218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 629107218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 629207218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6293e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 629407218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 629507218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 629607218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 629707218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 629807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 629907218a29SMatthew G. Knepley } 630007218a29SMatthew G. Knepley /* Get points */ 630107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 630207218a29SMatthew G. Knepley /* Get sizes */ 630307218a29SMatthew G. Knepley asize = 0; 630407218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 630507218a29SMatthew G. Knepley PetscInt dof; 630607218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 630707218a29SMatthew G. Knepley asize += dof; 630807218a29SMatthew G. Knepley } 630907218a29SMatthew G. Knepley if (values) { 631007218a29SMatthew G. Knepley const PetscScalar *vArray; 631107218a29SMatthew G. Knepley PetscInt size; 631207218a29SMatthew G. Knepley 631307218a29SMatthew G. Knepley if (*values) { 631407218a29SMatthew 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); 631507218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6316e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 631707218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 631807218a29SMatthew G. Knepley /* Get values */ 631907218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 632007218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 632107218a29SMatthew 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); 632207218a29SMatthew G. Knepley /* Cleanup array */ 632307218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 632407218a29SMatthew G. Knepley } 632507218a29SMatthew G. Knepley if (csize) *csize = asize; 632607218a29SMatthew G. Knepley /* Cleanup points */ 632707218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 632807218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 632907218a29SMatthew G. Knepley } 633007218a29SMatthew G. Knepley 6331552f7358SJed Brown /*@C 6332552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6333552f7358SJed Brown 6334552f7358SJed Brown Not collective 6335552f7358SJed Brown 6336552f7358SJed Brown Input Parameters: 6337a1cb98faSBarry Smith + dm - The `DM` 633820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6339552f7358SJed Brown . v - The local vector 6340a1cb98faSBarry Smith - point - The point in the `DM` 6341552f7358SJed Brown 63426b867d5aSJose E. Roman Input/Output Parameters: 634320f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 634420f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically; 634520f4b53cSBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed 634622c1ee49SMatthew G. Knepley 6347552f7358SJed Brown Level: intermediate 6348552f7358SJed Brown 6349a1cb98faSBarry Smith Notes: 635020f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6351a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6352a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6353a1cb98faSBarry Smith 6354a1cb98faSBarry Smith A typical use could be 6355a1cb98faSBarry Smith .vb 6356a1cb98faSBarry Smith values = NULL; 6357a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6358a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6359a1cb98faSBarry Smith <Compute on closure> 6360a1cb98faSBarry Smith } 6361a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6362a1cb98faSBarry Smith .ve 6363a1cb98faSBarry Smith or 6364a1cb98faSBarry Smith .vb 6365a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6366a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6367a1cb98faSBarry Smith clSize = clMaxSize; 6368a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6369a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6370a1cb98faSBarry Smith <Compute on closure> 6371a1cb98faSBarry Smith } 6372a1cb98faSBarry Smith } 6373a1cb98faSBarry Smith PetscFree(values); 6374a1cb98faSBarry Smith .ve 6375a1cb98faSBarry Smith 637660225df5SJacob Faibussowitsch Fortran Notes: 637720f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6378a1cb98faSBarry Smith 63791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6380552f7358SJed Brown @*/ 6381d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6382d71ae5a4SJacob Faibussowitsch { 6383d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6384e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 63853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6386552f7358SJed Brown } 6387552f7358SJed Brown 6388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6389d71ae5a4SJacob Faibussowitsch { 6390e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6391e5c487bfSMatthew G. Knepley PetscSection clSection; 6392e5c487bfSMatthew G. Knepley IS clPoints; 6393e5c487bfSMatthew G. Knepley PetscScalar *array; 6394e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6395e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6396c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6397c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6398e5c487bfSMatthew G. Knepley 6399e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6400e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 64019566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6402e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6403e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 64049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 64059566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 64069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6407e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 64089566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 64093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6410e5c487bfSMatthew G. Knepley } 6411e5c487bfSMatthew G. Knepley /* Get points */ 641207218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6413c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6414c459fbc1SJed Brown PetscInt dof; 64159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6416c459fbc1SJed Brown clsize += dof; 6417c459fbc1SJed Brown } 64189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6419e5c487bfSMatthew G. Knepley /* Filter points */ 6420e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6421e5c487bfSMatthew G. Knepley PetscInt dep; 6422e5c487bfSMatthew G. Knepley 64239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6424e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6425e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6426e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6427e5c487bfSMatthew G. Knepley ++Np; 6428e5c487bfSMatthew G. Knepley } 6429e5c487bfSMatthew G. Knepley /* Get array */ 6430e5c487bfSMatthew G. Knepley if (!values || !*values) { 6431e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6432e5c487bfSMatthew G. Knepley 6433e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 64349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6435e5c487bfSMatthew G. Knepley asize += dof; 6436e5c487bfSMatthew G. Knepley } 6437e5c487bfSMatthew G. Knepley if (!values) { 64389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6439e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 64403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6441e5c487bfSMatthew G. Knepley } 64429566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6443e5c487bfSMatthew G. Knepley } else { 6444e5c487bfSMatthew G. Knepley array = *values; 6445e5c487bfSMatthew G. Knepley } 64469566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6447e5c487bfSMatthew G. Knepley /* Get values */ 64489566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 64499566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6450e5c487bfSMatthew G. Knepley /* Cleanup points */ 64519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6452e5c487bfSMatthew G. Knepley /* Cleanup array */ 64539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6454e5c487bfSMatthew G. Knepley if (!*values) { 6455e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6456e5c487bfSMatthew G. Knepley *values = array; 6457e5c487bfSMatthew G. Knepley } else { 645863a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6459e5c487bfSMatthew G. Knepley *csize = size; 6460e5c487bfSMatthew G. Knepley } 64613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6462e5c487bfSMatthew G. Knepley } 6463e5c487bfSMatthew G. Knepley 6464552f7358SJed Brown /*@C 6465552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 6466552f7358SJed Brown 6467552f7358SJed Brown Not collective 6468552f7358SJed Brown 6469552f7358SJed Brown Input Parameters: 6470a1cb98faSBarry Smith + dm - The `DM` 647120f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6472552f7358SJed Brown . v - The local vector 6473a1cb98faSBarry Smith . point - The point in the `DM` 647420f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6475552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 6476552f7358SJed Brown 6477552f7358SJed Brown Level: intermediate 6478552f7358SJed Brown 6479a1cb98faSBarry Smith Note: 648020f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6481a1cb98faSBarry Smith 648260225df5SJacob Faibussowitsch Fortran Notes: 648320f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6484a1cb98faSBarry Smith 64851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6486552f7358SJed Brown @*/ 6487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6488d71ae5a4SJacob Faibussowitsch { 6489552f7358SJed Brown PetscInt size = 0; 6490552f7358SJed Brown 6491552f7358SJed Brown PetscFunctionBegin; 6492552f7358SJed Brown /* Should work without recalculating size */ 64939566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6494c9fdaa05SMatthew G. Knepley *values = NULL; 64953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6496552f7358SJed Brown } 6497552f7358SJed Brown 6498d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6499d71ae5a4SJacob Faibussowitsch { 65009371c9d4SSatish Balay *x += y; 65019371c9d4SSatish Balay } 6502d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6503d71ae5a4SJacob Faibussowitsch { 65049371c9d4SSatish Balay *x = y; 65059371c9d4SSatish Balay } 6506552f7358SJed Brown 6507d71ae5a4SJacob 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[]) 6508d71ae5a4SJacob Faibussowitsch { 6509552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6510552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6511552f7358SJed Brown PetscScalar *a; 6512552f7358SJed Brown PetscInt off, cind = 0, k; 6513552f7358SJed Brown 6514552f7358SJed Brown PetscFunctionBegin; 65159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6517552f7358SJed Brown a = &array[off]; 6518552f7358SJed Brown if (!cdof || setBC) { 651997e99dd9SToby Isaac if (clperm) { 65209371c9d4SSatish Balay if (perm) { 6521ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6522552f7358SJed Brown } else { 6523ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 65249371c9d4SSatish Balay } 65259371c9d4SSatish Balay } else { 65269371c9d4SSatish Balay if (perm) { 6527ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 65289371c9d4SSatish Balay } else { 6529ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 65309371c9d4SSatish Balay } 6531552f7358SJed Brown } 6532552f7358SJed Brown } else { 65339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 653497e99dd9SToby Isaac if (clperm) { 65359371c9d4SSatish Balay if (perm) { 65369371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 65379371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65389371c9d4SSatish Balay ++cind; 65399371c9d4SSatish Balay continue; 65409371c9d4SSatish Balay } 654197e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6542552f7358SJed Brown } 6543552f7358SJed Brown } else { 6544552f7358SJed Brown for (k = 0; k < dof; ++k) { 65459371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65469371c9d4SSatish Balay ++cind; 65479371c9d4SSatish Balay continue; 65489371c9d4SSatish Balay } 654997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 655097e99dd9SToby Isaac } 655197e99dd9SToby Isaac } 655297e99dd9SToby Isaac } else { 655397e99dd9SToby Isaac if (perm) { 655497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 65559371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65569371c9d4SSatish Balay ++cind; 65579371c9d4SSatish Balay continue; 65589371c9d4SSatish Balay } 655997e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 656097e99dd9SToby Isaac } 656197e99dd9SToby Isaac } else { 656297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 65639371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 65649371c9d4SSatish Balay ++cind; 65659371c9d4SSatish Balay continue; 65669371c9d4SSatish Balay } 656797e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 656897e99dd9SToby Isaac } 6569552f7358SJed Brown } 6570552f7358SJed Brown } 6571552f7358SJed Brown } 65723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6573552f7358SJed Brown } 6574552f7358SJed Brown 6575d71ae5a4SJacob 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[]) 6576d71ae5a4SJacob Faibussowitsch { 6577a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6578a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6579a5e93ea8SMatthew G. Knepley PetscScalar *a; 6580a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6581a5e93ea8SMatthew G. Knepley 6582a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 65839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 65849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6585a5e93ea8SMatthew G. Knepley a = &array[off]; 6586a5e93ea8SMatthew G. Knepley if (cdof) { 65879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 658897e99dd9SToby Isaac if (clperm) { 658997e99dd9SToby Isaac if (perm) { 6590a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6591a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 659297e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 659397e99dd9SToby Isaac cind++; 6594a5e93ea8SMatthew G. Knepley } 6595a5e93ea8SMatthew G. Knepley } 6596a5e93ea8SMatthew G. Knepley } else { 6597a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6598a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 659997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 660097e99dd9SToby Isaac cind++; 660197e99dd9SToby Isaac } 660297e99dd9SToby Isaac } 660397e99dd9SToby Isaac } 660497e99dd9SToby Isaac } else { 660597e99dd9SToby Isaac if (perm) { 660697e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 660797e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 660897e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 660997e99dd9SToby Isaac cind++; 661097e99dd9SToby Isaac } 661197e99dd9SToby Isaac } 661297e99dd9SToby Isaac } else { 661397e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 661497e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 661597e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 661697e99dd9SToby Isaac cind++; 661797e99dd9SToby Isaac } 6618a5e93ea8SMatthew G. Knepley } 6619a5e93ea8SMatthew G. Knepley } 6620a5e93ea8SMatthew G. Knepley } 6621a5e93ea8SMatthew G. Knepley } 66223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6623a5e93ea8SMatthew G. Knepley } 6624a5e93ea8SMatthew G. Knepley 6625d71ae5a4SJacob 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[]) 6626d71ae5a4SJacob Faibussowitsch { 6627552f7358SJed Brown PetscScalar *a; 66281a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 66291a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 663097e99dd9SToby Isaac PetscInt cind = 0, b; 6631552f7358SJed Brown 6632552f7358SJed Brown PetscFunctionBegin; 66339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 66349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 66359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 66361a271a75SMatthew G. Knepley a = &array[foff]; 6637552f7358SJed Brown if (!fcdof || setBC) { 663897e99dd9SToby Isaac if (clperm) { 66399371c9d4SSatish Balay if (perm) { 6640ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6641552f7358SJed Brown } else { 6642ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 66439371c9d4SSatish Balay } 66449371c9d4SSatish Balay } else { 66459371c9d4SSatish Balay if (perm) { 6646ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 66479371c9d4SSatish Balay } else { 6648ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 66499371c9d4SSatish Balay } 6650552f7358SJed Brown } 6651552f7358SJed Brown } else { 66529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 665397e99dd9SToby Isaac if (clperm) { 665497e99dd9SToby Isaac if (perm) { 665597e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66569371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66579371c9d4SSatish Balay ++cind; 66589371c9d4SSatish Balay continue; 66599371c9d4SSatish Balay } 666097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6661552f7358SJed Brown } 6662552f7358SJed Brown } else { 666397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66649371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66659371c9d4SSatish Balay ++cind; 66669371c9d4SSatish Balay continue; 66679371c9d4SSatish Balay } 666897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 666997e99dd9SToby Isaac } 667097e99dd9SToby Isaac } 667197e99dd9SToby Isaac } else { 667297e99dd9SToby Isaac if (perm) { 667397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66749371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66759371c9d4SSatish Balay ++cind; 66769371c9d4SSatish Balay continue; 66779371c9d4SSatish Balay } 667897e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 667997e99dd9SToby Isaac } 668097e99dd9SToby Isaac } else { 668197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 66829371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 66839371c9d4SSatish Balay ++cind; 66849371c9d4SSatish Balay continue; 66859371c9d4SSatish Balay } 668697e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6687552f7358SJed Brown } 6688552f7358SJed Brown } 6689552f7358SJed Brown } 6690552f7358SJed Brown } 66911a271a75SMatthew G. Knepley *offset += fdof; 66923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6693552f7358SJed Brown } 6694552f7358SJed Brown 6695d71ae5a4SJacob 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[]) 6696d71ae5a4SJacob Faibussowitsch { 6697a5e93ea8SMatthew G. Knepley PetscScalar *a; 66981a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 66991a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 67005da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6701ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6702a5e93ea8SMatthew G. Knepley 6703a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 67059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 67069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 67079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 67081a271a75SMatthew G. Knepley a = &array[foff]; 6709a5e93ea8SMatthew G. Knepley if (fcdof) { 6710ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 67119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 671297e99dd9SToby Isaac if (clperm) { 671397e99dd9SToby Isaac if (perm) { 6714ba322698SMatthew G. Knepley if (comps) { 6715ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6716ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67179371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67189371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67199371c9d4SSatish Balay ncSet = PETSC_TRUE; 67209371c9d4SSatish Balay } 67219371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67229371c9d4SSatish Balay ++cind; 67239371c9d4SSatish Balay fcSet = PETSC_TRUE; 67249371c9d4SSatish Balay } 6725ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6726ba322698SMatthew G. Knepley } 6727ba322698SMatthew G. Knepley } else { 672897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 672997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 673097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6731a5e93ea8SMatthew G. Knepley ++cind; 6732a5e93ea8SMatthew G. Knepley } 6733a5e93ea8SMatthew G. Knepley } 6734ba322698SMatthew G. Knepley } 6735ba322698SMatthew G. Knepley } else { 6736ba322698SMatthew G. Knepley if (comps) { 6737ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6738ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67399371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67409371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67419371c9d4SSatish Balay ncSet = PETSC_TRUE; 67429371c9d4SSatish Balay } 67439371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67449371c9d4SSatish Balay ++cind; 67459371c9d4SSatish Balay fcSet = PETSC_TRUE; 67469371c9d4SSatish Balay } 6747ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6748ba322698SMatthew G. Knepley } 6749a5e93ea8SMatthew G. Knepley } else { 675097e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 675197e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 675297e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 675397e99dd9SToby Isaac ++cind; 675497e99dd9SToby Isaac } 675597e99dd9SToby Isaac } 675697e99dd9SToby Isaac } 6757ba322698SMatthew G. Knepley } 675897e99dd9SToby Isaac } else { 675997e99dd9SToby Isaac if (perm) { 6760ba322698SMatthew G. Knepley if (comps) { 6761ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6762ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67639371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67649371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67659371c9d4SSatish Balay ncSet = PETSC_TRUE; 67669371c9d4SSatish Balay } 67679371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67689371c9d4SSatish Balay ++cind; 67699371c9d4SSatish Balay fcSet = PETSC_TRUE; 67709371c9d4SSatish Balay } 6771ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6772ba322698SMatthew G. Knepley } 6773ba322698SMatthew G. Knepley } else { 677497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 677597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 677697e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 677797e99dd9SToby Isaac ++cind; 677897e99dd9SToby Isaac } 677997e99dd9SToby Isaac } 6780ba322698SMatthew G. Knepley } 6781ba322698SMatthew G. Knepley } else { 6782ba322698SMatthew G. Knepley if (comps) { 6783ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6784ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 67859371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 67869371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 67879371c9d4SSatish Balay ncSet = PETSC_TRUE; 67889371c9d4SSatish Balay } 67899371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 67909371c9d4SSatish Balay ++cind; 67919371c9d4SSatish Balay fcSet = PETSC_TRUE; 67929371c9d4SSatish Balay } 6793ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6794ba322698SMatthew G. Knepley } 679597e99dd9SToby Isaac } else { 679697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 679797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 679897e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6799a5e93ea8SMatthew G. Knepley ++cind; 6800a5e93ea8SMatthew G. Knepley } 6801a5e93ea8SMatthew G. Knepley } 6802a5e93ea8SMatthew G. Knepley } 6803a5e93ea8SMatthew G. Knepley } 6804a5e93ea8SMatthew G. Knepley } 6805ba322698SMatthew G. Knepley } 68061a271a75SMatthew G. Knepley *offset += fdof; 68073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6808a5e93ea8SMatthew G. Knepley } 6809a5e93ea8SMatthew G. Knepley 6810d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6811d71ae5a4SJacob Faibussowitsch { 6812552f7358SJed Brown PetscScalar *array; 68131b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 68141b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 6815552f7358SJed Brown 68161b406b76SMatthew G. Knepley PetscFunctionBeginHot; 68179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 68189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 68199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 68209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 68219566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 6822b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 6823b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 6824b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 6825b6ebb6e6SMatthew G. Knepley 68269371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 68279371c9d4SSatish Balay dof = 0; 68289371c9d4SSatish Balay continue; 68299371c9d4SSatish Balay } 68309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 6831b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 6832b6ebb6e6SMatthew G. Knepley { 6833b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6834b6ebb6e6SMatthew G. Knepley PetscScalar *a; 6835b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 6836b6ebb6e6SMatthew G. Knepley 68379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 68389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 6839b6ebb6e6SMatthew G. Knepley a = &array[coff]; 6840b6ebb6e6SMatthew G. Knepley if (!cdof) { 6841b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6842ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 6843b6ebb6e6SMatthew G. Knepley } else { 6844ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 6845b6ebb6e6SMatthew G. Knepley } 6846b6ebb6e6SMatthew G. Knepley } else { 68479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 6848b6ebb6e6SMatthew G. Knepley if (o >= 0) { 6849b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 68509371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 68519371c9d4SSatish Balay ++cind; 68529371c9d4SSatish Balay continue; 68539371c9d4SSatish Balay } 6854b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 6855b6ebb6e6SMatthew G. Knepley } 6856b6ebb6e6SMatthew G. Knepley } else { 6857b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 68589371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 68599371c9d4SSatish Balay ++cind; 68609371c9d4SSatish Balay continue; 68619371c9d4SSatish Balay } 6862b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 6863b6ebb6e6SMatthew G. Knepley } 6864b6ebb6e6SMatthew G. Knepley } 6865b6ebb6e6SMatthew G. Knepley } 6866b6ebb6e6SMatthew G. Knepley } 6867b6ebb6e6SMatthew G. Knepley } 68689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 68693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6870b6ebb6e6SMatthew G. Knepley } 68711b406b76SMatthew G. Knepley 68721b406b76SMatthew G. Knepley /*@C 687320f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 68741b406b76SMatthew G. Knepley 68751b406b76SMatthew G. Knepley Not collective 68761b406b76SMatthew G. Knepley 68771b406b76SMatthew G. Knepley Input Parameters: 6878a1cb98faSBarry Smith + dm - The `DM` 687920f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 68801b406b76SMatthew G. Knepley . v - The local vector 688120f4b53cSBarry Smith . point - The point in the `DM` 68821b406b76SMatthew G. Knepley . values - The array of values 6883a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 6884a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 68851b406b76SMatthew G. Knepley 68861b406b76SMatthew G. Knepley Level: intermediate 68871b406b76SMatthew G. Knepley 68881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 68891b406b76SMatthew G. Knepley @*/ 6890d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 6891d71ae5a4SJacob Faibussowitsch { 68921b406b76SMatthew G. Knepley PetscSection clSection; 68931b406b76SMatthew G. Knepley IS clPoints; 68941b406b76SMatthew G. Knepley PetscScalar *array; 68951b406b76SMatthew G. Knepley PetscInt *points = NULL; 689627f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 6897c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 68981b406b76SMatthew G. Knepley 68991a271a75SMatthew G. Knepley PetscFunctionBeginHot; 69001b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 69019566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 69021a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 69031a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 69049566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 69059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 69061b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 69079566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 69083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69091b406b76SMatthew G. Knepley } 69101a271a75SMatthew G. Knepley /* Get points */ 691107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6912c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 6913c459fbc1SJed Brown PetscInt dof; 69149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6915c459fbc1SJed Brown clsize += dof; 6916c459fbc1SJed Brown } 69179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 69181a271a75SMatthew G. Knepley /* Get array */ 69199566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 69201a271a75SMatthew G. Knepley /* Get values */ 6921ef90cfe2SMatthew G. Knepley if (numFields > 0) { 692297e99dd9SToby Isaac PetscInt offset = 0, f; 6923552f7358SJed Brown for (f = 0; f < numFields; ++f) { 692497e99dd9SToby Isaac const PetscInt **perms = NULL; 692597e99dd9SToby Isaac const PetscScalar **flips = NULL; 692697e99dd9SToby Isaac 69279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 6928552f7358SJed Brown switch (mode) { 6929552f7358SJed Brown case INSERT_VALUES: 693097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 693197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 693297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 693397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69343ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 69359371c9d4SSatish Balay } 69369371c9d4SSatish Balay break; 6937552f7358SJed Brown case INSERT_ALL_VALUES: 693897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 693997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 694097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 694197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69423ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 69439371c9d4SSatish Balay } 69449371c9d4SSatish Balay break; 6945a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 694697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 694797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 694897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 694997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69503ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 69519371c9d4SSatish Balay } 69529371c9d4SSatish Balay break; 6953552f7358SJed Brown case ADD_VALUES: 695497e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 695597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 695697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 695797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69583ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 69599371c9d4SSatish Balay } 69609371c9d4SSatish Balay break; 6961552f7358SJed Brown case ADD_ALL_VALUES: 696297e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 696397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 696497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 696597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69663ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 69679371c9d4SSatish Balay } 69689371c9d4SSatish Balay break; 6969304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 697097e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 697197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 697297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 697397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69743ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 69759371c9d4SSatish Balay } 69769371c9d4SSatish Balay break; 6977d71ae5a4SJacob Faibussowitsch default: 6978d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 6979552f7358SJed Brown } 69809566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 69811a271a75SMatthew G. Knepley } 6982552f7358SJed Brown } else { 69831a271a75SMatthew G. Knepley PetscInt dof, off; 698497e99dd9SToby Isaac const PetscInt **perms = NULL; 698597e99dd9SToby Isaac const PetscScalar **flips = NULL; 69861a271a75SMatthew G. Knepley 69879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 6988552f7358SJed Brown switch (mode) { 6989552f7358SJed Brown case INSERT_VALUES: 699097e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 699197e99dd9SToby Isaac const PetscInt point = points[2 * p]; 699297e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 699397e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 69949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 69953ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 69969371c9d4SSatish Balay } 69979371c9d4SSatish Balay break; 6998552f7358SJed Brown case INSERT_ALL_VALUES: 699997e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 700097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 700197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 700297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70043ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70059371c9d4SSatish Balay } 70069371c9d4SSatish Balay break; 7007a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 700897e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 700997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 701197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70133ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 70149371c9d4SSatish Balay } 70159371c9d4SSatish Balay break; 7016552f7358SJed Brown case ADD_VALUES: 701797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 701897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 701997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70223ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 70239371c9d4SSatish Balay } 70249371c9d4SSatish Balay break; 7025552f7358SJed Brown case ADD_ALL_VALUES: 702697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 702797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 702897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 702997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70313ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 70329371c9d4SSatish Balay } 70339371c9d4SSatish Balay break; 7034304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 703597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 703697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 703797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 703897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 70399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 70403ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 70419371c9d4SSatish Balay } 70429371c9d4SSatish Balay break; 7043d71ae5a4SJacob Faibussowitsch default: 7044d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7045552f7358SJed Brown } 70469566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7047552f7358SJed Brown } 70481a271a75SMatthew G. Knepley /* Cleanup points */ 70499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 70501a271a75SMatthew G. Knepley /* Cleanup array */ 70519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 70523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7053552f7358SJed Brown } 7054552f7358SJed Brown 70555f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7056d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7057d71ae5a4SJacob Faibussowitsch { 70585f790a90SMatthew G. Knepley PetscFunctionBegin; 705911cc89d2SBarry Smith *contains = PETSC_TRUE; 70605f790a90SMatthew G. Knepley if (label) { 7061d6177c40SToby Isaac PetscInt fdof; 70625f790a90SMatthew G. Knepley 706311cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 706411cc89d2SBarry Smith if (!*contains) { 70659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 70665f790a90SMatthew G. Knepley *offset += fdof; 70673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70685f790a90SMatthew G. Knepley } 70695f790a90SMatthew G. Knepley } 70703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70715f790a90SMatthew G. Knepley } 70725f790a90SMatthew G. Knepley 707397529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7074d71ae5a4SJacob 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) 7075d71ae5a4SJacob Faibussowitsch { 7076e07394fbSMatthew G. Knepley PetscSection clSection; 7077e07394fbSMatthew G. Knepley IS clPoints; 7078e07394fbSMatthew G. Knepley PetscScalar *array; 7079e07394fbSMatthew G. Knepley PetscInt *points = NULL; 708097529cf3SJed Brown const PetscInt *clp; 7081e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 708297e99dd9SToby Isaac PetscInt offset = 0, f; 7083e07394fbSMatthew G. Knepley 7084e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7085e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 70869566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7087e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7088e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 70899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7090e07394fbSMatthew G. Knepley /* Get points */ 709107218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7092e07394fbSMatthew G. Knepley /* Get array */ 70939566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7094e07394fbSMatthew G. Knepley /* Get values */ 7095e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 709697e99dd9SToby Isaac const PetscInt **perms = NULL; 709797e99dd9SToby Isaac const PetscScalar **flips = NULL; 709811cc89d2SBarry Smith PetscBool contains; 709997e99dd9SToby Isaac 7100e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7101e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7102e07394fbSMatthew G. Knepley PetscInt fdof; 71039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7104e07394fbSMatthew G. Knepley offset += fdof; 7105e07394fbSMatthew G. Knepley } 7106e07394fbSMatthew G. Knepley continue; 7107e07394fbSMatthew G. Knepley } 71089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7109e07394fbSMatthew G. Knepley switch (mode) { 7110e07394fbSMatthew G. Knepley case INSERT_VALUES: 711197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 711297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 711397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 711497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 711511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 711611cc89d2SBarry Smith if (!contains) continue; 71179566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 71189371c9d4SSatish Balay } 71199371c9d4SSatish Balay break; 7120e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 712197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 712297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 712397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 712497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 712511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 712611cc89d2SBarry Smith if (!contains) continue; 71279566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 71289371c9d4SSatish Balay } 71299371c9d4SSatish Balay break; 7130e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 713197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 713297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 713397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 713497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 713511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 713611cc89d2SBarry Smith if (!contains) continue; 71379566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 71389371c9d4SSatish Balay } 71399371c9d4SSatish Balay break; 7140e07394fbSMatthew G. Knepley case ADD_VALUES: 714197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 714297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 714397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 714497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 714511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 714611cc89d2SBarry Smith if (!contains) continue; 71479566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 71489371c9d4SSatish Balay } 71499371c9d4SSatish Balay break; 7150e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 715197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 715297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 715397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 715497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 715511cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 715611cc89d2SBarry Smith if (!contains) continue; 71579566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 71589371c9d4SSatish Balay } 71599371c9d4SSatish Balay break; 7160d71ae5a4SJacob Faibussowitsch default: 7161d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7162e07394fbSMatthew G. Knepley } 71639566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7164e07394fbSMatthew G. Knepley } 7165e07394fbSMatthew G. Knepley /* Cleanup points */ 71669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7167e07394fbSMatthew G. Knepley /* Cleanup array */ 71689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 71693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7170e07394fbSMatthew G. Knepley } 7171e07394fbSMatthew G. Knepley 7172d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7173d71ae5a4SJacob Faibussowitsch { 7174552f7358SJed Brown PetscMPIInt rank; 7175552f7358SJed Brown PetscInt i, j; 7176552f7358SJed Brown 7177552f7358SJed Brown PetscFunctionBegin; 71789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 717963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 718063a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 718163a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7182b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 71833ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7184b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 71859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7186b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7187519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 71889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7189552f7358SJed Brown #else 71909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7191552f7358SJed Brown #endif 7192552f7358SJed Brown } 71939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7194552f7358SJed Brown } 71953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7196552f7358SJed Brown } 7197552f7358SJed Brown 719805586334SMatthew G. Knepley /* 719905586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 720005586334SMatthew G. Knepley 720105586334SMatthew G. Knepley Input Parameters: 720205586334SMatthew G. Knepley + section - The section for this data layout 720336fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 720405586334SMatthew G. Knepley . point - The point contributing dofs with these indices 720505586334SMatthew G. Knepley . off - The global offset of this point 720605586334SMatthew G. Knepley . loff - The local offset of each field 7207a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 720805586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 720905586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 721005586334SMatthew G. Knepley 721105586334SMatthew G. Knepley Output Parameter: 721205586334SMatthew G. Knepley . indices - Indices for dofs on this point 721305586334SMatthew G. Knepley 721405586334SMatthew G. Knepley Level: developer 721505586334SMatthew G. Knepley 721605586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 721705586334SMatthew G. Knepley */ 7218d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7219d71ae5a4SJacob Faibussowitsch { 7220e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7221552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7222552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7223552f7358SJed Brown PetscInt cind = 0, k; 7224552f7358SJed Brown 7225552f7358SJed Brown PetscFunctionBegin; 722608401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 72279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7229552f7358SJed Brown if (!cdof || setBC) { 723005586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 723105586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 723205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 723305586334SMatthew G. Knepley 723405586334SMatthew G. Knepley indices[ind] = off + k; 7235552f7358SJed Brown } 7236552f7358SJed Brown } else { 72379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 72384acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 723905586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 724005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 724105586334SMatthew G. Knepley 72424acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 72434acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 724405586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 72454acb8e1eSToby Isaac ++cind; 72464acb8e1eSToby Isaac } else { 724736fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7248552f7358SJed Brown } 7249552f7358SJed Brown } 7250552f7358SJed Brown } 7251e6ccafaeSMatthew G Knepley *loff += dof; 72523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7253552f7358SJed Brown } 7254552f7358SJed Brown 72557e29afd2SMatthew G. Knepley /* 725636fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 72577e29afd2SMatthew G. Knepley 725836fa2b79SJed Brown Input Parameters: 725936fa2b79SJed Brown + section - a section (global or local) 726020f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 726136fa2b79SJed Brown . point - point within section 726236fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 726336fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 726436fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 726536fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 726636fa2b79SJed Brown . permsoff - offset 726736fa2b79SJed Brown - indperm - index permutation 726836fa2b79SJed Brown 726936fa2b79SJed Brown Output Parameter: 727036fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 727136fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 727236fa2b79SJed Brown 727336fa2b79SJed Brown Notes: 727436fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 727536fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 727636fa2b79SJed Brown in the local vector. 727736fa2b79SJed Brown 727836fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 727936fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 728036fa2b79SJed Brown 728136fa2b79SJed Brown Developer Note: 728236fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 728336fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 728436fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 728536fa2b79SJed Brown 728636fa2b79SJed Brown Example: 728736fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 728836fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 728936fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 729036fa2b79SJed 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. 729136fa2b79SJed Brown 729236fa2b79SJed Brown Level: developer 72937e29afd2SMatthew G. Knepley */ 7294d71ae5a4SJacob 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[]) 7295d71ae5a4SJacob Faibussowitsch { 7296552f7358SJed Brown PetscInt numFields, foff, f; 7297552f7358SJed Brown 7298552f7358SJed Brown PetscFunctionBegin; 729908401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 73009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7301552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 73024acb8e1eSToby Isaac PetscInt fdof, cfdof; 7303552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73044acb8e1eSToby Isaac PetscInt cind = 0, b; 73054acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7306552f7358SJed Brown 73079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7309552f7358SJed Brown if (!cfdof || setBC) { 731005586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 731105586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 731205586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 731305586334SMatthew G. Knepley 731405586334SMatthew G. Knepley indices[ind] = off + foff + b; 731505586334SMatthew G. Knepley } 7316552f7358SJed Brown } else { 73179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 731805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 731905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 732005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 732105586334SMatthew G. Knepley 73224acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 732305586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7324552f7358SJed Brown ++cind; 7325552f7358SJed Brown } else { 732636fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7327552f7358SJed Brown } 7328552f7358SJed Brown } 7329552f7358SJed Brown } 733036fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7331552f7358SJed Brown foffs[f] += fdof; 7332552f7358SJed Brown } 73333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7334552f7358SJed Brown } 7335552f7358SJed Brown 73367e29afd2SMatthew G. Knepley /* 73377e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 73387e29afd2SMatthew G. Knepley 73397e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7340645102dcSJed Brown 7341645102dcSJed Brown Notes: 7342645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7343645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 73447e29afd2SMatthew G. Knepley */ 7345d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7346d71ae5a4SJacob Faibussowitsch { 73477e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 73487e29afd2SMatthew G. Knepley 73497e29afd2SMatthew G. Knepley PetscFunctionBegin; 73509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 73517e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 73527e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 73537e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 73547e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 73557e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 73567e29afd2SMatthew G. Knepley 73579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 73589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 73599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7360645102dcSJed Brown if (!cfdof) { 736105586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 736205586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 736305586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 736405586334SMatthew G. Knepley 736505586334SMatthew G. Knepley indices[ind] = foff + b; 736605586334SMatthew G. Knepley } 73677e29afd2SMatthew G. Knepley } else { 73689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 736905586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 737005586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 737105586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 737205586334SMatthew G. Knepley 73737e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 737405586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 73757e29afd2SMatthew G. Knepley ++cind; 73767e29afd2SMatthew G. Knepley } else { 737705586334SMatthew G. Knepley indices[ind] = foff + b - cind; 73787e29afd2SMatthew G. Knepley } 73797e29afd2SMatthew G. Knepley } 73807e29afd2SMatthew G. Knepley } 73817e29afd2SMatthew G. Knepley foffs[f] += fdof; 73827e29afd2SMatthew G. Knepley } 73833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 73847e29afd2SMatthew G. Knepley } 73857e29afd2SMatthew G. Knepley 7386d71ae5a4SJacob 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) 7387d71ae5a4SJacob Faibussowitsch { 7388d3d1a6afSToby Isaac Mat cMat; 7389d3d1a6afSToby Isaac PetscSection aSec, cSec; 7390d3d1a6afSToby Isaac IS aIS; 7391d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7392d3d1a6afSToby Isaac const PetscInt *anchors; 7393e17c06e0SMatthew G. Knepley PetscInt numFields, f, p, q, newP = 0; 7394d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7395d3d1a6afSToby Isaac PetscInt *newPoints, *indices, *newIndices; 7396d3d1a6afSToby Isaac PetscInt maxAnchor, maxDof; 7397d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7398d3d1a6afSToby Isaac PetscInt *pointMatOffsets[32]; 7399d3d1a6afSToby Isaac PetscInt *newPointOffsets[32]; 7400d3d1a6afSToby Isaac PetscScalar *pointMat[32]; 74016ecaa68aSToby Isaac PetscScalar *newValues = NULL, *tmpValues; 7402d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7403d3d1a6afSToby Isaac 7404d3d1a6afSToby Isaac PetscFunctionBegin; 7405d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7406d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 74079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7408d3d1a6afSToby Isaac 74099566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7410d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7411d3d1a6afSToby Isaac if (aSec) { 74129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 74139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 74149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7415d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7416d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7417d3d1a6afSToby Isaac * into the global matrix anyway) */ 7418d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7419d3d1a6afSToby Isaac PetscInt b = points[p]; 74204b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7421d3d1a6afSToby Isaac 74229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7423ad540459SPierre Jolivet if (!bSecDof) continue; 742448a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7425d3d1a6afSToby Isaac if (bDof) { 7426d3d1a6afSToby Isaac /* this point is constrained */ 7427d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7428d3d1a6afSToby Isaac PetscInt bOff, q; 7429d3d1a6afSToby Isaac 7430d3d1a6afSToby Isaac anyConstrained = PETSC_TRUE; 7431d3d1a6afSToby Isaac newNumPoints += bDof; 74329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7433d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7434d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7435d3d1a6afSToby Isaac PetscInt aDof; 7436d3d1a6afSToby Isaac 74379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7438d3d1a6afSToby Isaac newNumIndices += aDof; 7439d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7440d3d1a6afSToby Isaac PetscInt fDof; 7441d3d1a6afSToby Isaac 74429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7443d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7444d3d1a6afSToby Isaac } 7445d3d1a6afSToby Isaac } 74469371c9d4SSatish Balay } else { 7447d3d1a6afSToby Isaac /* this point is not constrained */ 7448d3d1a6afSToby Isaac newNumPoints++; 74494b2f2278SToby Isaac newNumIndices += bSecDof; 7450d3d1a6afSToby Isaac for (f = 0; f < numFields; ++f) { 7451d3d1a6afSToby Isaac PetscInt fDof; 7452d3d1a6afSToby Isaac 74539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7454d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7455d3d1a6afSToby Isaac } 7456d3d1a6afSToby Isaac } 7457d3d1a6afSToby Isaac } 7458d3d1a6afSToby Isaac } 7459d3d1a6afSToby Isaac if (!anyConstrained) { 746072b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 746172b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 746272b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 746372b80496SMatthew G. Knepley if (outValues) *outValues = NULL; 74649566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 74653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7466d3d1a6afSToby Isaac } 7467d3d1a6afSToby Isaac 74686ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 74696ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 74706ecaa68aSToby Isaac 7471f13f9184SToby Isaac for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7472d3d1a6afSToby Isaac 74736ecaa68aSToby Isaac if (!outPoints && !outValues) { 74746ecaa68aSToby Isaac if (offsets) { 7475ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 74766ecaa68aSToby Isaac } 74779566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 74783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74796ecaa68aSToby Isaac } 74806ecaa68aSToby Isaac 74811dca8a05SBarry 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); 7482d3d1a6afSToby Isaac 74839566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7484d3d1a6afSToby Isaac 7485d3d1a6afSToby Isaac /* workspaces */ 7486d3d1a6afSToby Isaac if (numFields) { 7487d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 74889566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 74899566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7490d3d1a6afSToby Isaac } 74919371c9d4SSatish Balay } else { 74929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 74939566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0])); 7494d3d1a6afSToby Isaac } 7495d3d1a6afSToby Isaac 7496d3d1a6afSToby Isaac /* get workspaces for the point-to-point matrices */ 7497d3d1a6afSToby Isaac if (numFields) { 74984b2f2278SToby Isaac PetscInt totalOffset, totalMatOffset; 74994b2f2278SToby Isaac 7500d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7501d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 75024b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7503d3d1a6afSToby Isaac 75049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75054b2f2278SToby Isaac if (!bSecDof) { 75064b2f2278SToby Isaac for (f = 0; f < numFields; f++) { 75074b2f2278SToby Isaac newPointOffsets[f][p + 1] = 0; 75084b2f2278SToby Isaac pointMatOffsets[f][p + 1] = 0; 75094b2f2278SToby Isaac } 75104b2f2278SToby Isaac continue; 75114b2f2278SToby Isaac } 751248a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7513d3d1a6afSToby Isaac if (bDof) { 7514d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7515d3d1a6afSToby Isaac PetscInt fDof, q, bOff, allFDof = 0; 7516d3d1a6afSToby Isaac 75179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 75189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7519d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7520d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7521d3d1a6afSToby Isaac PetscInt aFDof; 7522d3d1a6afSToby Isaac 75239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof)); 7524d3d1a6afSToby Isaac allFDof += aFDof; 7525d3d1a6afSToby Isaac } 7526d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = allFDof; 7527d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = fDof * allFDof; 7528d3d1a6afSToby Isaac } 75299371c9d4SSatish Balay } else { 7530d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7531d3d1a6afSToby Isaac PetscInt fDof; 7532d3d1a6afSToby Isaac 75339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7534d3d1a6afSToby Isaac newPointOffsets[f][p + 1] = fDof; 7535d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] = 0; 7536d3d1a6afSToby Isaac } 7537d3d1a6afSToby Isaac } 7538d3d1a6afSToby Isaac } 75394b2f2278SToby Isaac for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) { 75404b2f2278SToby Isaac newPointOffsets[f][0] = totalOffset; 75414b2f2278SToby Isaac pointMatOffsets[f][0] = totalMatOffset; 7542d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7543d3d1a6afSToby Isaac newPointOffsets[f][p + 1] += newPointOffsets[f][p]; 7544d3d1a6afSToby Isaac pointMatOffsets[f][p + 1] += pointMatOffsets[f][p]; 7545d3d1a6afSToby Isaac } 754619f70fd5SToby Isaac totalOffset = newPointOffsets[f][numPoints]; 754719f70fd5SToby Isaac totalMatOffset = pointMatOffsets[f][numPoints]; 75489566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 7549d3d1a6afSToby Isaac } 75509371c9d4SSatish Balay } else { 7551d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7552d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 75534b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7554d3d1a6afSToby Isaac 75559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 75564b2f2278SToby Isaac if (!bSecDof) { 75574b2f2278SToby Isaac newPointOffsets[0][p + 1] = 0; 75584b2f2278SToby Isaac pointMatOffsets[0][p + 1] = 0; 75594b2f2278SToby Isaac continue; 75604b2f2278SToby Isaac } 756148a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7562d3d1a6afSToby Isaac if (bDof) { 75634b2f2278SToby Isaac PetscInt bOff, q, allDof = 0; 7564d3d1a6afSToby Isaac 75659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7566d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7567d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aDof; 7568d3d1a6afSToby Isaac 75699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 7570d3d1a6afSToby Isaac allDof += aDof; 7571d3d1a6afSToby Isaac } 7572d3d1a6afSToby Isaac newPointOffsets[0][p + 1] = allDof; 75734b2f2278SToby Isaac pointMatOffsets[0][p + 1] = bSecDof * allDof; 75749371c9d4SSatish Balay } else { 75754b2f2278SToby Isaac newPointOffsets[0][p + 1] = bSecDof; 7576d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] = 0; 7577d3d1a6afSToby Isaac } 7578d3d1a6afSToby Isaac } 7579d3d1a6afSToby Isaac newPointOffsets[0][0] = 0; 7580d3d1a6afSToby Isaac pointMatOffsets[0][0] = 0; 7581d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7582d3d1a6afSToby Isaac newPointOffsets[0][p + 1] += newPointOffsets[0][p]; 7583d3d1a6afSToby Isaac pointMatOffsets[0][p + 1] += pointMatOffsets[0][p]; 7584d3d1a6afSToby Isaac } 75859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 7586d3d1a6afSToby Isaac } 7587d3d1a6afSToby Isaac 75886ecaa68aSToby Isaac /* output arrays */ 75899566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 75906ecaa68aSToby Isaac 7591d3d1a6afSToby Isaac /* get the point-to-point matrices; construct newPoints */ 75929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor)); 75939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetMaxDof(section, &maxDof)); 75949566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices)); 75959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 7596d3d1a6afSToby Isaac if (numFields) { 7597d3d1a6afSToby Isaac for (p = 0, newP = 0; p < numPoints; p++) { 7598d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7599d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 76004b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7601d3d1a6afSToby Isaac 76029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7603ad540459SPierre Jolivet if (!bSecDof) continue; 760448a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7605d3d1a6afSToby Isaac if (bDof) { 7606d3d1a6afSToby Isaac PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 7607d3d1a6afSToby Isaac 7608d3d1a6afSToby Isaac fStart[0] = 0; 7609d3d1a6afSToby Isaac fEnd[0] = 0; 7610d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7611d3d1a6afSToby Isaac PetscInt fDof; 7612d3d1a6afSToby Isaac 76139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof)); 7614d3d1a6afSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7615d3d1a6afSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7616d3d1a6afSToby Isaac } 76179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76189566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices)); 7619d3d1a6afSToby Isaac 7620d3d1a6afSToby Isaac fAnchorStart[0] = 0; 7621d3d1a6afSToby Isaac fAnchorEnd[0] = 0; 7622d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7623d3d1a6afSToby Isaac PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 7624d3d1a6afSToby Isaac 7625d3d1a6afSToby Isaac fAnchorStart[f + 1] = fAnchorStart[f] + fDof; 7626d3d1a6afSToby Isaac fAnchorEnd[f + 1] = fAnchorStart[f + 1]; 7627d3d1a6afSToby Isaac } 76289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7629d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7630d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7631d3d1a6afSToby Isaac 7632d3d1a6afSToby 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 */ 7633d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7634d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 76359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 76369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices)); 7637d3d1a6afSToby Isaac } 7638d3d1a6afSToby Isaac newP += bDof; 7639d3d1a6afSToby Isaac 76406ecaa68aSToby Isaac if (outValues) { 7641d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 764248a46eb9SPierre 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])); 7643d3d1a6afSToby Isaac } 76449371c9d4SSatish Balay } else { 7645d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7646d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7647d3d1a6afSToby Isaac newP++; 7648d3d1a6afSToby Isaac } 7649d3d1a6afSToby Isaac } 7650d3d1a6afSToby Isaac } else { 7651d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7652d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7653d3d1a6afSToby Isaac PetscInt o = points[2 * p + 1]; 76544b2f2278SToby Isaac PetscInt bDof = 0, bSecDof; 7655d3d1a6afSToby Isaac 76569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7657ad540459SPierre Jolivet if (!bSecDof) continue; 765848a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7659d3d1a6afSToby Isaac if (bDof) { 7660d3d1a6afSToby Isaac PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 7661d3d1a6afSToby Isaac 76629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, b, &bOff)); 76639566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices)); 7664d3d1a6afSToby Isaac 76659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7666d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7667d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q], aOff; 7668d3d1a6afSToby Isaac 7669d3d1a6afSToby 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 */ 7670d3d1a6afSToby Isaac 7671d3d1a6afSToby Isaac newPoints[2 * (newP + q)] = a; 7672d3d1a6afSToby Isaac newPoints[2 * (newP + q) + 1] = 0; 76739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 76749566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices)); 7675d3d1a6afSToby Isaac } 7676d3d1a6afSToby Isaac newP += bDof; 7677d3d1a6afSToby Isaac 7678d3d1a6afSToby Isaac /* get the point-to-point submatrix */ 767948a46eb9SPierre Jolivet if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p])); 76809371c9d4SSatish Balay } else { 7681d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7682d3d1a6afSToby Isaac newPoints[2 * newP + 1] = o; 7683d3d1a6afSToby Isaac newP++; 7684d3d1a6afSToby Isaac } 7685d3d1a6afSToby Isaac } 7686d3d1a6afSToby Isaac } 7687d3d1a6afSToby Isaac 76886ecaa68aSToby Isaac if (outValues) { 76899566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 76909566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices)); 7691d3d1a6afSToby Isaac /* multiply constraints on the right */ 7692d3d1a6afSToby Isaac if (numFields) { 7693d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7694d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7695d3d1a6afSToby Isaac 7696d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7697d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[f][p]; 7698d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7699d3d1a6afSToby Isaac PetscInt c, r, k; 7700d3d1a6afSToby Isaac PetscInt dof; 7701d3d1a6afSToby Isaac 77029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7703ad540459SPierre Jolivet if (!dof) continue; 7704d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7705d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[f][p + 1] - cStart; 7706d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 7707d3d1a6afSToby Isaac 7708d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7709d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7710ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c]; 7711d3d1a6afSToby Isaac } 7712d3d1a6afSToby Isaac } 77139371c9d4SSatish Balay } else { 7714d3d1a6afSToby Isaac /* copy this column as is */ 7715d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7716ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7717d3d1a6afSToby Isaac } 7718d3d1a6afSToby Isaac } 7719d3d1a6afSToby Isaac oldOff += dof; 7720d3d1a6afSToby Isaac } 7721d3d1a6afSToby Isaac } 77229371c9d4SSatish Balay } else { 7723d3d1a6afSToby Isaac PetscInt oldOff = 0; 7724d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7725d3d1a6afSToby Isaac PetscInt cStart = newPointOffsets[0][p]; 7726d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7727d3d1a6afSToby Isaac PetscInt c, r, k; 7728d3d1a6afSToby Isaac PetscInt dof; 7729d3d1a6afSToby Isaac 77309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7731ad540459SPierre Jolivet if (!dof) continue; 7732d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7733d3d1a6afSToby Isaac PetscInt nCols = newPointOffsets[0][p + 1] - cStart; 7734d3d1a6afSToby Isaac const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 7735d3d1a6afSToby Isaac 7736d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7737d3d1a6afSToby Isaac for (c = 0; c < nCols; c++) { 7738ad540459SPierre Jolivet for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 7739d3d1a6afSToby Isaac } 7740d3d1a6afSToby Isaac } 77419371c9d4SSatish Balay } else { 7742d3d1a6afSToby Isaac /* copy this column as is */ 7743d3d1a6afSToby Isaac for (r = 0; r < numIndices; r++) { 7744ad540459SPierre Jolivet for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 7745d3d1a6afSToby Isaac } 7746d3d1a6afSToby Isaac } 7747d3d1a6afSToby Isaac oldOff += dof; 7748d3d1a6afSToby Isaac } 7749d3d1a6afSToby Isaac } 7750d3d1a6afSToby Isaac 77516ecaa68aSToby Isaac if (multiplyLeft) { 77529566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues)); 77539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices)); 7754d3d1a6afSToby Isaac /* multiply constraints transpose on the left */ 7755d3d1a6afSToby Isaac if (numFields) { 7756d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 7757d3d1a6afSToby Isaac PetscInt oldOff = offsets[f]; 7758d3d1a6afSToby Isaac 7759d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7760d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[f][p]; 7761d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7762d3d1a6afSToby Isaac PetscInt c, r, k; 7763d3d1a6afSToby Isaac PetscInt dof; 7764d3d1a6afSToby Isaac 77659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &dof)); 7766d3d1a6afSToby Isaac if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 7767d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[f][p + 1] - rStart; 7768d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 7769d3d1a6afSToby Isaac 7770d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7771d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7772ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7773d3d1a6afSToby Isaac } 7774d3d1a6afSToby Isaac } 77759371c9d4SSatish Balay } else { 7776d3d1a6afSToby Isaac /* copy this row as is */ 7777d3d1a6afSToby Isaac for (r = 0; r < dof; r++) { 7778ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7779d3d1a6afSToby Isaac } 7780d3d1a6afSToby Isaac } 7781d3d1a6afSToby Isaac oldOff += dof; 7782d3d1a6afSToby Isaac } 7783d3d1a6afSToby Isaac } 77849371c9d4SSatish Balay } else { 7785d3d1a6afSToby Isaac PetscInt oldOff = 0; 7786d3d1a6afSToby Isaac 7787d3d1a6afSToby Isaac for (p = 0; p < numPoints; p++) { 7788d3d1a6afSToby Isaac PetscInt rStart = newPointOffsets[0][p]; 7789d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7790d3d1a6afSToby Isaac PetscInt c, r, k; 7791d3d1a6afSToby Isaac PetscInt dof; 7792d3d1a6afSToby Isaac 77939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, b, &dof)); 7794d3d1a6afSToby Isaac if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 7795d3d1a6afSToby Isaac PetscInt nRows = newPointOffsets[0][p + 1] - rStart; 7796d3d1a6afSToby Isaac const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 7797d3d1a6afSToby Isaac 7798d3d1a6afSToby Isaac for (r = 0; r < nRows; r++) { 7799d3d1a6afSToby Isaac for (c = 0; c < newNumIndices; c++) { 7800ad540459SPierre Jolivet for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 7801d3d1a6afSToby Isaac } 7802d3d1a6afSToby Isaac } 78039371c9d4SSatish Balay } else { 7804d3d1a6afSToby Isaac /* copy this row as is */ 78059fc93327SToby Isaac for (r = 0; r < dof; r++) { 7806ad540459SPierre Jolivet for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 7807d3d1a6afSToby Isaac } 7808d3d1a6afSToby Isaac } 7809d3d1a6afSToby Isaac oldOff += dof; 7810d3d1a6afSToby Isaac } 7811d3d1a6afSToby Isaac } 7812d3d1a6afSToby Isaac 78139566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues)); 78149371c9d4SSatish Balay } else { 78156ecaa68aSToby Isaac newValues = tmpValues; 78166ecaa68aSToby Isaac } 78176ecaa68aSToby Isaac } 78186ecaa68aSToby Isaac 7819d3d1a6afSToby Isaac /* clean up */ 78209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices)); 78219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices)); 78226ecaa68aSToby Isaac 7823d3d1a6afSToby Isaac if (numFields) { 7824d3d1a6afSToby Isaac for (f = 0; f < numFields; f++) { 78259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f])); 78269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f])); 78279566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f])); 7828d3d1a6afSToby Isaac } 78299371c9d4SSatish Balay } else { 78309566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0])); 78319566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0])); 78329566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0])); 7833d3d1a6afSToby Isaac } 78349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7835d3d1a6afSToby Isaac 7836d3d1a6afSToby Isaac /* output */ 78376ecaa68aSToby Isaac if (outPoints) { 7838d3d1a6afSToby Isaac *outPoints = newPoints; 78399371c9d4SSatish Balay } else { 78409566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 78416ecaa68aSToby Isaac } 7842ad540459SPierre Jolivet if (outValues) *outValues = newValues; 7843ad540459SPierre Jolivet for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 78443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7845d3d1a6afSToby Isaac } 7846d3d1a6afSToby Isaac 78474a1e0b3eSMatthew G. Knepley /*@C 784871f0bbf9SMatthew G. Knepley DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 78497cd05799SMatthew G. Knepley 78507cd05799SMatthew G. Knepley Not collective 78517cd05799SMatthew G. Knepley 78527cd05799SMatthew G. Knepley Input Parameters: 7853a1cb98faSBarry Smith + dm - The `DM` 7854a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 7855a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 785671f0bbf9SMatthew G. Knepley . point - The point defining the closure 785771f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 78587cd05799SMatthew G. Knepley 785971f0bbf9SMatthew G. Knepley Output Parameters: 786071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 786171f0bbf9SMatthew G. Knepley . indices - The dof indices 786220f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 786320f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 78647cd05799SMatthew G. Knepley 7865a1cb98faSBarry Smith Level: advanced 786636fa2b79SJed Brown 7867a1cb98faSBarry Smith Notes: 7868a1cb98faSBarry Smith Must call `DMPlexRestoreClosureIndices()` to free allocated memory 7869a1cb98faSBarry Smith 787020f4b53cSBarry Smith If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 787120f4b53cSBarry Smith of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 787236fa2b79SJed Brown of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 787320f4b53cSBarry Smith indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 787436fa2b79SJed Brown indices (with the above semantics) are implied. 78757cd05799SMatthew G. Knepley 78761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 7877a1cb98faSBarry Smith `PetscSection`, `DMGetGlobalSection()` 78784a1e0b3eSMatthew G. Knepley @*/ 7879d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 7880d71ae5a4SJacob Faibussowitsch { 788171f0bbf9SMatthew G. Knepley /* Closure ordering */ 78827773e69fSMatthew G. Knepley PetscSection clSection; 78837773e69fSMatthew G. Knepley IS clPoints; 788471f0bbf9SMatthew G. Knepley const PetscInt *clp; 788571f0bbf9SMatthew G. Knepley PetscInt *points; 788671f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 788771f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 78884acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 788971f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 789071f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 789171f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 789271f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 789371f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 789471f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 789571f0bbf9SMatthew G. Knepley 789671f0bbf9SMatthew G. Knepley PetscInt *idx; 789771f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 789871f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 78997773e69fSMatthew G. Knepley 790071f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 79017773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79027773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 790336fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 79044f572ea9SToby Isaac if (numIndices) PetscAssertPointer(numIndices, 6); 79054f572ea9SToby Isaac if (indices) PetscAssertPointer(indices, 7); 79064f572ea9SToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 8); 79074f572ea9SToby Isaac if (values) PetscAssertPointer(values, 9); 79089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 790963a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 79109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 791171f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 791207218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7913c459fbc1SJed Brown if (useClPerm) { 7914c459fbc1SJed Brown PetscInt depth, clsize; 79159566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7916c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7917c459fbc1SJed Brown PetscInt dof; 79189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7919c459fbc1SJed Brown clsize += dof; 7920c459fbc1SJed Brown } 79219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7922c459fbc1SJed Brown } 792371f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 792471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 79257773e69fSMatthew G. Knepley PetscInt dof, fdof; 79267773e69fSMatthew G. Knepley 79279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 79287773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 79299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 79307773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 79317773e69fSMatthew G. Knepley } 793271f0bbf9SMatthew G. Knepley Ni += dof; 79337773e69fSMatthew G. Knepley } 79347773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 79351dca8a05SBarry 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); 793671f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 793771f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79389566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79399566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 794071f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 794171f0bbf9SMatthew G. Knepley if (values && flips[f]) { 794271f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 79436ecaa68aSToby Isaac 794471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 794571f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 794671f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 794771f0bbf9SMatthew G. Knepley 79489566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 79499566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 795071f0bbf9SMatthew G. Knepley if (flip) { 795171f0bbf9SMatthew G. Knepley PetscInt i, j, k; 795271f0bbf9SMatthew G. Knepley 795371f0bbf9SMatthew G. Knepley if (!valCopy) { 79549566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 795571f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 795671f0bbf9SMatthew G. Knepley *values = valCopy; 795771f0bbf9SMatthew G. Knepley } 795871f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 795971f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 796071f0bbf9SMatthew G. Knepley 796171f0bbf9SMatthew G. Knepley for (k = 0; k < Ni; ++k) { 796271f0bbf9SMatthew G. Knepley valCopy[Ni * (foffset + i) + k] *= fval; 796371f0bbf9SMatthew G. Knepley valCopy[Ni * k + (foffset + i)] *= fval; 79646ecaa68aSToby Isaac } 79656ecaa68aSToby Isaac } 796671f0bbf9SMatthew G. Knepley } 796771f0bbf9SMatthew G. Knepley foffset += fdof; 796871f0bbf9SMatthew G. Knepley } 796971f0bbf9SMatthew G. Knepley } 797071f0bbf9SMatthew G. Knepley } 797171f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 79729566063dSJacob Faibussowitsch PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE)); 797371f0bbf9SMatthew G. Knepley if (NclC) { 79749566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 797571f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79769566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 79779566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 797871f0bbf9SMatthew G. Knepley } 797971f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 79809566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 79819566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 798271f0bbf9SMatthew G. Knepley } 79839566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 798471f0bbf9SMatthew G. Knepley Ncl = NclC; 798571f0bbf9SMatthew G. Knepley Ni = NiC; 798671f0bbf9SMatthew G. Knepley points = pointsC; 798771f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 798871f0bbf9SMatthew G. Knepley } 798971f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 79909566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 799171f0bbf9SMatthew G. Knepley if (Nf) { 799271f0bbf9SMatthew G. Knepley PetscInt idxOff; 799371f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 799471f0bbf9SMatthew G. Knepley 79959371c9d4SSatish Balay if (outOffsets) { 79969371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 79979371c9d4SSatish Balay } 79989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 799971f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 800071f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 800171f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 800271f0bbf9SMatthew G. Knepley 80039566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 80047773e69fSMatthew G. Knepley } 80057773e69fSMatthew G. Knepley } else { 800671f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 800771f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 800871f0bbf9SMatthew G. Knepley 80099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 801071f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 801171f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 801271f0bbf9SMatthew G. Knepley * global section. */ 80139566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 801471f0bbf9SMatthew G. Knepley } 801571f0bbf9SMatthew G. Knepley } 801671f0bbf9SMatthew G. Knepley } else { 801771f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 801871f0bbf9SMatthew G. Knepley 801971f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 802071f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 80214acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 80224acb8e1eSToby Isaac 80239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 802471f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 802571f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 80269566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 80277773e69fSMatthew G. Knepley } 80287773e69fSMatthew G. Knepley } 802971f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 803071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80319566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80329566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 80334acb8e1eSToby Isaac } 803471f0bbf9SMatthew G. Knepley if (NclC) { 80359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 80367773e69fSMatthew G. Knepley } else { 80379566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 80387773e69fSMatthew G. Knepley } 803971f0bbf9SMatthew G. Knepley 804071f0bbf9SMatthew G. Knepley if (numIndices) *numIndices = Ni; 804171f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 80423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80437773e69fSMatthew G. Knepley } 80447773e69fSMatthew G. Knepley 80457cd05799SMatthew G. Knepley /*@C 804671f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 80477cd05799SMatthew G. Knepley 80487cd05799SMatthew G. Knepley Not collective 80497cd05799SMatthew G. Knepley 80507cd05799SMatthew G. Knepley Input Parameters: 8051a1cb98faSBarry Smith + dm - The `DM` 8052a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8053a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 805471f0bbf9SMatthew G. Knepley . point - The point defining the closure 805571f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 805671f0bbf9SMatthew G. Knepley 805771f0bbf9SMatthew G. Knepley Output Parameters: 805871f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 805971f0bbf9SMatthew G. Knepley . indices - The dof indices 806020f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 806120f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 806271f0bbf9SMatthew G. Knepley 8063a1cb98faSBarry Smith Level: advanced 806471f0bbf9SMatthew G. Knepley 8065a1cb98faSBarry Smith Notes: 8066a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8067a1cb98faSBarry Smith 8068a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 806971f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 807071f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 807171f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 807271f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 80737cd05799SMatthew G. Knepley 80741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 80757cd05799SMatthew G. Knepley @*/ 8076d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8077d71ae5a4SJacob Faibussowitsch { 80787773e69fSMatthew G. Knepley PetscFunctionBegin; 80797773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80804f572ea9SToby Isaac PetscAssertPointer(indices, 7); 80819566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 80823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 80837773e69fSMatthew G. Knepley } 80847773e69fSMatthew G. Knepley 8085e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8086d71ae5a4SJacob Faibussowitsch { 8087552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8088552f7358SJed Brown PetscInt *indices; 808971f0bbf9SMatthew G. Knepley PetscInt numIndices; 809071f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8091552f7358SJed Brown PetscErrorCode ierr; 8092552f7358SJed Brown 8093552f7358SJed Brown PetscFunctionBegin; 8094552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 80959566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 80963dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 80979566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 80983dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8099e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8100552f7358SJed Brown 8101e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81020d644c17SKarl Rupp 81039566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8104d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 81054a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8106552f7358SJed Brown if (ierr) { 8107552f7358SJed Brown PetscMPIInt rank; 8108552f7358SJed Brown 81099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 81109566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 81119566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 81129566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81139566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8114c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8115552f7358SJed Brown } 81164a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 81174a1e0b3eSMatthew G. Knepley PetscInt i; 81189566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 811963a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 81209566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 81214a1e0b3eSMatthew G. Knepley } 812271f0bbf9SMatthew G. Knepley 81239566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 81249566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 81253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81264acb8e1eSToby Isaac } 812771f0bbf9SMatthew G. Knepley 81284a1e0b3eSMatthew G. Knepley /*@C 8129e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8130e8e188d2SZach Atkins 8131e8e188d2SZach Atkins Not collective 8132e8e188d2SZach Atkins 8133e8e188d2SZach Atkins Input Parameters: 8134e8e188d2SZach Atkins + dm - The `DM` 8135e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8136e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8137e8e188d2SZach Atkins . A - The matrix 8138e8e188d2SZach Atkins . point - The point in the `DM` 8139e8e188d2SZach Atkins . values - The array of values 8140e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8141e8e188d2SZach Atkins 8142e8e188d2SZach Atkins Level: intermediate 8143e8e188d2SZach Atkins 8144e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8145e8e188d2SZach Atkins @*/ 8146e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8147e8e188d2SZach Atkins { 8148e8e188d2SZach Atkins PetscFunctionBegin; 8149e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8150e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8151e8e188d2SZach Atkins } 8152e8e188d2SZach Atkins 8153e8e188d2SZach Atkins /*@C 815460225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 81554a1e0b3eSMatthew G. Knepley 81564a1e0b3eSMatthew G. Knepley Not collective 81574a1e0b3eSMatthew G. Knepley 81584a1e0b3eSMatthew G. Knepley Input Parameters: 8159a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 816020f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8161e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 816220f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8163a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 816420f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8165e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 816620f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 81674a1e0b3eSMatthew G. Knepley . A - The matrix 8168a1cb98faSBarry Smith . point - The point in the `DM` 81694a1e0b3eSMatthew G. Knepley . values - The array of values 8170a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 81714a1e0b3eSMatthew G. Knepley 81724a1e0b3eSMatthew G. Knepley Level: intermediate 81734a1e0b3eSMatthew G. Knepley 81741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 81754a1e0b3eSMatthew G. Knepley @*/ 8176e8e188d2SZach 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) 8177d71ae5a4SJacob Faibussowitsch { 817871f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 817971f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 818071f0bbf9SMatthew G. Knepley PetscInt numIndicesRow, numIndicesCol; 818171f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 818271f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 818371f0bbf9SMatthew G. Knepley 818471f0bbf9SMatthew G. Knepley PetscFunctionBegin; 818571f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 81869566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 818771f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 81889566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 818971f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8190e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 81919566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8192e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 81939566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8194e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8195e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 819671f0bbf9SMatthew G. Knepley 8197e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8198e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 819971f0bbf9SMatthew G. Knepley 82009566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 8201d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 82024a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode); 820371f0bbf9SMatthew G. Knepley if (ierr) { 820471f0bbf9SMatthew G. Knepley PetscMPIInt rank; 820571f0bbf9SMatthew G. Knepley 82069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82079566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82089566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 82099566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 82109566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values)); 82119566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 8212d3d1a6afSToby Isaac } 821371f0bbf9SMatthew G. Knepley 8214e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values)); 8215e8e188d2SZach Atkins PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values)); 82169566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values)); 82173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8218552f7358SJed Brown } 8219552f7358SJed Brown 8220d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8221d71ae5a4SJacob Faibussowitsch { 8222de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8223de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8224de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8225de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 822617c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8227de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8228412e9a14SMatthew G. Knepley DMPolytopeType ct; 82294ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8230de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8231de41b84cSMatthew G. Knepley 8232de41b84cSMatthew G. Knepley PetscFunctionBegin; 8233de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8234de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 82359566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8236de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 82379566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8238de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 82399566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8240de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 82419566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8242de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8243de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 82449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 824563a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 82469566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 82479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8248de41b84cSMatthew G. Knepley /* Column indices */ 82499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 82504ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8251de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8252de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 82539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8254de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8255de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8256de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8257de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8258de41b84cSMatthew G. Knepley ++q; 8259de41b84cSMatthew G. Knepley } 8260de41b84cSMatthew G. Knepley } 8261de41b84cSMatthew G. Knepley numCPoints = q; 8262de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8263de41b84cSMatthew G. Knepley PetscInt fdof; 8264de41b84cSMatthew G. Knepley 82659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 82664ca5e9f5SMatthew G. Knepley if (!dof) continue; 8267de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 82689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8269de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8270de41b84cSMatthew G. Knepley } 8271de41b84cSMatthew G. Knepley numCIndices += dof; 8272de41b84cSMatthew G. Knepley } 8273de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8274de41b84cSMatthew G. Knepley /* Row indices */ 82759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8276412e9a14SMatthew G. Knepley { 8277012bc364SMatthew G. Knepley DMPlexTransform tr; 8278012bc364SMatthew G. Knepley DMPolytopeType *rct; 8279012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8280012bc364SMatthew G. Knepley 82819566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 82829566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 82839566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8284012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 82859566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8286412e9a14SMatthew G. Knepley } 82879566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8288de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8289de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 82909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8291de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 82929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8293de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8294de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 82959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 82964ca5e9f5SMatthew G. Knepley if (!dof) continue; 82979371c9d4SSatish Balay for (s = 0; s < q; ++s) 82989371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 82994ca5e9f5SMatthew G. Knepley if (s < q) continue; 8300de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8301de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8302de41b84cSMatthew G. Knepley ++q; 8303de41b84cSMatthew G. Knepley } 8304de41b84cSMatthew G. Knepley } 83059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8306de41b84cSMatthew G. Knepley } 8307de41b84cSMatthew G. Knepley numFPoints = q; 8308de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8309de41b84cSMatthew G. Knepley PetscInt fdof; 8310de41b84cSMatthew G. Knepley 83119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 83124ca5e9f5SMatthew G. Knepley if (!dof) continue; 8313de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 83149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8315de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8316de41b84cSMatthew G. Knepley } 8317de41b84cSMatthew G. Knepley numFIndices += dof; 8318de41b84cSMatthew G. Knepley } 8319de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8320de41b84cSMatthew G. Knepley 83211dca8a05SBarry 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); 83221dca8a05SBarry 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); 83239566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83249566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8325de41b84cSMatthew G. Knepley if (numFields) { 83264acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 83274acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 83284acb8e1eSToby Isaac 83294acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8332de41b84cSMatthew G. Knepley } 83334acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 83349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83359566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 83364acb8e1eSToby Isaac } 83374acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 83389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83399566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 83404acb8e1eSToby Isaac } 83414acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 83429566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 83439566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8344de41b84cSMatthew G. Knepley } 8345de41b84cSMatthew G. Knepley } else { 83464acb8e1eSToby Isaac const PetscInt **permsF = NULL; 83474acb8e1eSToby Isaac const PetscInt **permsC = NULL; 83484acb8e1eSToby Isaac 83499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 83514acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 83524acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 83534acb8e1eSToby Isaac 83549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 83559566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8356de41b84cSMatthew G. Knepley } 83574acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 83584acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 83594acb8e1eSToby Isaac 83609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 83619566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8362de41b84cSMatthew G. Knepley } 83639566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 83649566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8365de41b84cSMatthew G. Knepley } 83669566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83674acb8e1eSToby Isaac /* TODO: flips */ 8368d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8369de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8370de41b84cSMatthew G. Knepley if (ierr) { 8371de41b84cSMatthew G. Knepley PetscMPIInt rank; 8372de41b84cSMatthew G. Knepley 83739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 83749566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 83759566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 83769566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83779566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8378de41b84cSMatthew G. Knepley } 83799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 83809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83819566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 83829566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 83833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8384de41b84cSMatthew G. Knepley } 8385de41b84cSMatthew G. Knepley 8386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8387d71ae5a4SJacob Faibussowitsch { 83887c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 83897c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 83907c927364SMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 839117c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8392412e9a14SMatthew G. Knepley DMPolytopeType ct; 83937c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 83947c927364SMatthew G. Knepley 83957c927364SMatthew G. Knepley PetscFunctionBegin; 83967c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 83977c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83989566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 83997c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 84009566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 84017c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 84029566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 84037c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 84049566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 84057c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 84069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 840763a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 84089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 84099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 84107c927364SMatthew G. Knepley /* Column indices */ 84119566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 84127c927364SMatthew G. Knepley maxFPoints = numCPoints; 84137c927364SMatthew G. Knepley /* Compress out points not in the section */ 84147c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 84159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 84167c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 84177c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 84187c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 84197c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 84207c927364SMatthew G. Knepley ++q; 84217c927364SMatthew G. Knepley } 84227c927364SMatthew G. Knepley } 84237c927364SMatthew G. Knepley numCPoints = q; 84247c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 84257c927364SMatthew G. Knepley PetscInt fdof; 84267c927364SMatthew G. Knepley 84279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 84287c927364SMatthew G. Knepley if (!dof) continue; 84297c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 84317c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 84327c927364SMatthew G. Knepley } 84337c927364SMatthew G. Knepley numCIndices += dof; 84347c927364SMatthew G. Knepley } 84357c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 84367c927364SMatthew G. Knepley /* Row indices */ 84379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8438412e9a14SMatthew G. Knepley { 8439012bc364SMatthew G. Knepley DMPlexTransform tr; 8440012bc364SMatthew G. Knepley DMPolytopeType *rct; 8441012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8442012bc364SMatthew G. Knepley 84439566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 84449566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 84459566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8446012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 84479566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8448412e9a14SMatthew G. Knepley } 84499566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 84507c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 84517c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 84529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 84537c927364SMatthew G. Knepley /* Compress out points not in the section */ 84549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 84557c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 84567c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 84579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 84587c927364SMatthew G. Knepley if (!dof) continue; 84599371c9d4SSatish Balay for (s = 0; s < q; ++s) 84609371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 84617c927364SMatthew G. Knepley if (s < q) continue; 84627c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 84637c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 84647c927364SMatthew G. Knepley ++q; 84657c927364SMatthew G. Knepley } 84667c927364SMatthew G. Knepley } 84679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 84687c927364SMatthew G. Knepley } 84697c927364SMatthew G. Knepley numFPoints = q; 84707c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 84717c927364SMatthew G. Knepley PetscInt fdof; 84727c927364SMatthew G. Knepley 84739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 84747c927364SMatthew G. Knepley if (!dof) continue; 84757c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 84777c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 84787c927364SMatthew G. Knepley } 84797c927364SMatthew G. Knepley numFIndices += dof; 84807c927364SMatthew G. Knepley } 84817c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 84827c927364SMatthew G. Knepley 84831dca8a05SBarry 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); 84841dca8a05SBarry 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); 84857c927364SMatthew G. Knepley if (numFields) { 84864acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84874acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84884acb8e1eSToby Isaac 84894acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 84927c927364SMatthew G. Knepley } 84934acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84959566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84964acb8e1eSToby Isaac } 84974acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84999566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 85004acb8e1eSToby Isaac } 85014acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 85029566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 85039566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 85047c927364SMatthew G. Knepley } 85057c927364SMatthew G. Knepley } else { 85064acb8e1eSToby Isaac const PetscInt **permsF = NULL; 85074acb8e1eSToby Isaac const PetscInt **permsC = NULL; 85084acb8e1eSToby Isaac 85099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85114acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 85124acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 85134acb8e1eSToby Isaac 85149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 85159566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 85167c927364SMatthew G. Knepley } 85174acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 85184acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 85194acb8e1eSToby Isaac 85209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85219566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 85227c927364SMatthew G. Knepley } 85239566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85249566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 85257c927364SMatthew G. Knepley } 85269566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 85279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85297c927364SMatthew G. Knepley } 85307c927364SMatthew G. Knepley 85317cd05799SMatthew G. Knepley /*@C 85327cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 85337cd05799SMatthew G. Knepley 85347cd05799SMatthew G. Knepley Input Parameter: 8535a1cb98faSBarry Smith . dm - The `DMPLEX` object 85367cd05799SMatthew G. Knepley 85377cd05799SMatthew G. Knepley Output Parameter: 85387cd05799SMatthew G. Knepley . cellHeight - The height of a cell 85397cd05799SMatthew G. Knepley 85407cd05799SMatthew G. Knepley Level: developer 85417cd05799SMatthew G. Knepley 85421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 85437cd05799SMatthew G. Knepley @*/ 8544d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8545d71ae5a4SJacob Faibussowitsch { 8546552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8547552f7358SJed Brown 8548552f7358SJed Brown PetscFunctionBegin; 8549552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85504f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8551552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 85523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8553552f7358SJed Brown } 8554552f7358SJed Brown 85557cd05799SMatthew G. Knepley /*@C 85567cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 85577cd05799SMatthew G. Knepley 85587cd05799SMatthew G. Knepley Input Parameters: 8559a1cb98faSBarry Smith + dm - The `DMPLEX` object 85607cd05799SMatthew G. Knepley - cellHeight - The height of a cell 85617cd05799SMatthew G. Knepley 85627cd05799SMatthew G. Knepley Level: developer 85637cd05799SMatthew G. Knepley 85641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 85657cd05799SMatthew G. Knepley @*/ 8566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8567d71ae5a4SJacob Faibussowitsch { 8568552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8569552f7358SJed Brown 8570552f7358SJed Brown PetscFunctionBegin; 8571552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8572552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 85733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8574552f7358SJed Brown } 8575552f7358SJed Brown 8576e6139122SMatthew G. Knepley /*@ 85772827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8578e6139122SMatthew G. Knepley 85792827ebadSStefano Zampini Input Parameters: 85802827ebadSStefano Zampini + dm - The `DMPLEX` object 85812827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8582e6139122SMatthew G. Knepley 8583e6139122SMatthew G. Knepley Output Parameters: 85842827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 85852827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8586e6139122SMatthew G. Knepley 85872a9f31c0SMatthew G. Knepley Level: advanced 8588e6139122SMatthew G. Knepley 85892827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8590e6139122SMatthew G. Knepley @*/ 85912827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8592d71ae5a4SJacob Faibussowitsch { 85932827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 85942827ebadSStefano Zampini DMLabel label; 85952827ebadSStefano Zampini PetscInt pStart, pEnd; 8596e6139122SMatthew G. Knepley 8597e6139122SMatthew G. Knepley PetscFunctionBegin; 8598e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 85992827ebadSStefano Zampini if (start) { 86004f572ea9SToby Isaac PetscAssertPointer(start, 3); 86012827ebadSStefano Zampini *start = 0; 86022827ebadSStefano Zampini } 86032827ebadSStefano Zampini if (end) { 86044f572ea9SToby Isaac PetscAssertPointer(end, 4); 86052827ebadSStefano Zampini *end = 0; 86062827ebadSStefano Zampini } 86072827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 86082827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 86092827ebadSStefano Zampini if (mesh->tr) { 86102827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 86112827ebadSStefano Zampini } else { 86122827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 86132827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 86142827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 86152827ebadSStefano Zampini } 86163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8617e6139122SMatthew G. Knepley } 8618e6139122SMatthew G. Knepley 8619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8620d71ae5a4SJacob Faibussowitsch { 8621552f7358SJed Brown PetscSection section, globalSection; 8622552f7358SJed Brown PetscInt *numbers, p; 8623552f7358SJed Brown 8624552f7358SJed Brown PetscFunctionBegin; 8625d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 86269566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 86279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 862848a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 86299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 86309566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection)); 86319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8632552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 86339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8634ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8635ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8636552f7358SJed Brown } 86379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8638ef48cebcSMatthew G. Knepley if (globalSize) { 8639ef48cebcSMatthew G. Knepley PetscLayout layout; 86409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 86419566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 86429566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8643ef48cebcSMatthew G. Knepley } 86449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 86459566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 86463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8647552f7358SJed Brown } 8648552f7358SJed Brown 8649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) 8650d71ae5a4SJacob Faibussowitsch { 8651412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8652552f7358SJed Brown 8653552f7358SJed Brown PetscFunctionBegin; 86549566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 86559566063dSJacob Faibussowitsch if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 86569566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 86579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 86583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8659552f7358SJed Brown } 866081ed3555SMatthew G. Knepley 86618dab3259SMatthew G. Knepley /*@ 86627cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 86637cd05799SMatthew G. Knepley 86647cd05799SMatthew G. Knepley Input Parameter: 8665a1cb98faSBarry Smith . dm - The `DMPLEX` object 86667cd05799SMatthew G. Knepley 86677cd05799SMatthew G. Knepley Output Parameter: 86687cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 86697cd05799SMatthew G. Knepley 86707cd05799SMatthew G. Knepley Level: developer 86717cd05799SMatthew G. Knepley 86721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()` 86737cd05799SMatthew G. Knepley @*/ 8674d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8675d71ae5a4SJacob Faibussowitsch { 867681ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 867781ed3555SMatthew G. Knepley 867881ed3555SMatthew G. Knepley PetscFunctionBegin; 867981ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86809566063dSJacob Faibussowitsch if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8681552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 86823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8683552f7358SJed Brown } 8684552f7358SJed Brown 8685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8686d71ae5a4SJacob Faibussowitsch { 8687412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 868881ed3555SMatthew G. Knepley 868981ed3555SMatthew G. Knepley PetscFunctionBegin; 869081ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86919566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 86929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 86933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869481ed3555SMatthew G. Knepley } 869581ed3555SMatthew G. Knepley 86968dab3259SMatthew G. Knepley /*@ 86976aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 86987cd05799SMatthew G. Knepley 86997cd05799SMatthew G. Knepley Input Parameter: 8700a1cb98faSBarry Smith . dm - The `DMPLEX` object 87017cd05799SMatthew G. Knepley 87027cd05799SMatthew G. Knepley Output Parameter: 87037cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 87047cd05799SMatthew G. Knepley 87057cd05799SMatthew G. Knepley Level: developer 87067cd05799SMatthew G. Knepley 87071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87087cd05799SMatthew G. Knepley @*/ 8709d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8710d71ae5a4SJacob Faibussowitsch { 8711552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8712552f7358SJed Brown 8713552f7358SJed Brown PetscFunctionBegin; 8714552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87159566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8716552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 87173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8718552f7358SJed Brown } 8719552f7358SJed Brown 87208dab3259SMatthew G. Knepley /*@ 8721966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8722966484cfSJed Brown 872320f4b53cSBarry Smith Collective 87247cd05799SMatthew G. Knepley 87257cd05799SMatthew G. Knepley Input Parameter: 8726a1cb98faSBarry Smith . dm - The `DMPLEX` object 87277cd05799SMatthew G. Knepley 87287cd05799SMatthew G. Knepley Output Parameter: 87297cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 87307cd05799SMatthew G. Knepley 8731a1cb98faSBarry Smith Level: developer 8732966484cfSJed Brown 8733a1cb98faSBarry Smith Notes: 8734a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8735966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8736966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8737966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8738966484cfSJed Brown 8739966484cfSJed Brown The partitioned mesh is 8740966484cfSJed Brown ``` 8741966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8742966484cfSJed Brown ``` 8743966484cfSJed Brown and its global numbering is 8744966484cfSJed Brown ``` 8745966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8746966484cfSJed Brown ``` 8747966484cfSJed Brown Then the global numbering is provided as 8748966484cfSJed Brown ``` 8749966484cfSJed Brown [0] Number of indices in set 5 8750966484cfSJed Brown [0] 0 0 8751966484cfSJed Brown [0] 1 1 8752966484cfSJed Brown [0] 2 3 8753966484cfSJed Brown [0] 3 4 8754966484cfSJed Brown [0] 4 -6 8755966484cfSJed Brown [1] Number of indices in set 3 8756966484cfSJed Brown [1] 0 2 8757966484cfSJed Brown [1] 1 5 8758966484cfSJed Brown [1] 2 6 8759966484cfSJed Brown ``` 8760966484cfSJed Brown 87611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 87627cd05799SMatthew G. Knepley @*/ 8763d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8764d71ae5a4SJacob Faibussowitsch { 8765ef48cebcSMatthew G. Knepley IS nums[4]; 8766862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8767ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 87680c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8769ef48cebcSMatthew G. Knepley 8770ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8771ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 87730c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 87749566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 87750c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8776862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8777862913ffSStefano Zampini PetscInt end; 8778862913ffSStefano Zampini 8779862913ffSStefano Zampini depths[d] = depth - d; 87809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 87810c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8782862913ffSStefano Zampini } 87830c15888dSMatthew G. Knepley if (empty) 87840c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 87850c15888dSMatthew G. Knepley depths[d] = -1; 87860c15888dSMatthew G. Knepley starts[d] = -1; 87870c15888dSMatthew G. Knepley } 87880c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 87891c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8790ad540459SPierre 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]); 87910c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8792ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8793ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8794ef48cebcSMatthew G. Knepley 87959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 87969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8797ef48cebcSMatthew G. Knepley shift += gsize; 8798ef48cebcSMatthew G. Knepley } 8799d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 88009566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 88013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8802ef48cebcSMatthew G. Knepley } 8803ef48cebcSMatthew G. Knepley 880408a22f4bSMatthew G. Knepley /*@ 880508a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 880608a22f4bSMatthew G. Knepley 880708a22f4bSMatthew G. Knepley Input Parameter: 8808a1cb98faSBarry Smith . dm - The `DMPLEX` object 880908a22f4bSMatthew G. Knepley 881008a22f4bSMatthew G. Knepley Output Parameter: 881108a22f4bSMatthew G. Knepley . ranks - The rank field 881208a22f4bSMatthew G. Knepley 8813a1cb98faSBarry Smith Options Database Key: 881420f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 881508a22f4bSMatthew G. Knepley 881608a22f4bSMatthew G. Knepley Level: intermediate 881708a22f4bSMatthew G. Knepley 88181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 881908a22f4bSMatthew G. Knepley @*/ 8820d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 8821d71ae5a4SJacob Faibussowitsch { 882208a22f4bSMatthew G. Knepley DM rdm; 882308a22f4bSMatthew G. Knepley PetscFE fe; 882408a22f4bSMatthew G. Knepley PetscScalar *r; 882508a22f4bSMatthew G. Knepley PetscMPIInt rank; 8826a55f9a55SMatthew G. Knepley DMPolytopeType ct; 882708a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 8828a55f9a55SMatthew G. Knepley PetscBool simplex; 882908a22f4bSMatthew G. Knepley 883008a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 8831f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88324f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 88339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 88349566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 88359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 88369566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 88379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 8838a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 88399566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 88409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 88419566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 88429566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 88439566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 88449566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 88459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 88469566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 884708a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 884808a22f4bSMatthew G. Knepley PetscScalar *lr; 884908a22f4bSMatthew G. Knepley 88509566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 885171f09efeSPierre Jolivet if (lr) *lr = rank; 885208a22f4bSMatthew G. Knepley } 88539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 88549566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 88553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885608a22f4bSMatthew G. Knepley } 885708a22f4bSMatthew G. Knepley 8858ca8062c8SMatthew G. Knepley /*@ 885918e14f0cSMatthew G. Knepley DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell 886018e14f0cSMatthew G. Knepley 886118e14f0cSMatthew G. Knepley Input Parameters: 886220f4b53cSBarry Smith + dm - The `DMPLEX` 886320f4b53cSBarry Smith - label - The `DMLabel` 886418e14f0cSMatthew G. Knepley 886518e14f0cSMatthew G. Knepley Output Parameter: 886618e14f0cSMatthew G. Knepley . val - The label value field 886718e14f0cSMatthew G. Knepley 886820f4b53cSBarry Smith Options Database Key: 886920f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 887018e14f0cSMatthew G. Knepley 887118e14f0cSMatthew G. Knepley Level: intermediate 887218e14f0cSMatthew G. Knepley 88731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 887418e14f0cSMatthew G. Knepley @*/ 8875d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 8876d71ae5a4SJacob Faibussowitsch { 887718e14f0cSMatthew G. Knepley DM rdm; 887818e14f0cSMatthew G. Knepley PetscFE fe; 887918e14f0cSMatthew G. Knepley PetscScalar *v; 888018e14f0cSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 888118e14f0cSMatthew G. Knepley 888218e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 888318e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88844f572ea9SToby Isaac PetscAssertPointer(label, 2); 88854f572ea9SToby Isaac PetscAssertPointer(val, 3); 88869566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 88879566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 88889566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe)); 88899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "label_value")); 88909566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 88919566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 88929566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 88939566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 88949566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 88959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*val, "label_value")); 88969566063dSJacob Faibussowitsch PetscCall(VecGetArray(*val, &v)); 889718e14f0cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 889818e14f0cSMatthew G. Knepley PetscScalar *lv; 889918e14f0cSMatthew G. Knepley PetscInt cval; 890018e14f0cSMatthew G. Knepley 89019566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv)); 89029566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &cval)); 890318e14f0cSMatthew G. Knepley *lv = cval; 890418e14f0cSMatthew G. Knepley } 89059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*val, &v)); 89069566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 89073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 890818e14f0cSMatthew G. Knepley } 890918e14f0cSMatthew G. Knepley 891018e14f0cSMatthew G. Knepley /*@ 8911ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 8912ca8062c8SMatthew G. Knepley 891369916449SMatthew G. Knepley Input Parameter: 8914a1cb98faSBarry Smith . dm - The `DMPLEX` object 8915a1cb98faSBarry Smith 8916a1cb98faSBarry Smith Level: developer 8917ca8062c8SMatthew G. Knepley 891895eb5ee5SVaclav Hapla Notes: 891995eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 892095eb5ee5SVaclav Hapla 892120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 8922ca8062c8SMatthew G. Knepley 89231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 8924ca8062c8SMatthew G. Knepley @*/ 8925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 8926d71ae5a4SJacob Faibussowitsch { 8927ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 8928ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 8929ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 893057beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 893157beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 8932ca8062c8SMatthew G. Knepley 8933ca8062c8SMatthew G. Knepley PetscFunctionBegin; 8934ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89359566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 89369566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 89379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 8938ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 89399566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 8940ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 89419566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 89429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 8943ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 894442e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 894542e66dfaSMatthew G. Knepley PetscInt d; 894642e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 89479371c9d4SSatish Balay if (cone[c] == cone[d]) { 89489371c9d4SSatish Balay dup = PETSC_TRUE; 89499371c9d4SSatish Balay break; 89509371c9d4SSatish Balay } 895142e66dfaSMatthew G. Knepley } 89529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 89539566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 8954ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 8955ca8062c8SMatthew G. Knepley if (support[s] == p) break; 8956ca8062c8SMatthew G. Knepley } 895742e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 895863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 895948a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 89609566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 896163a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 896248a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 89639566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 896463a3b9bcSJacob 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]); 8965f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 8966ca8062c8SMatthew G. Knepley } 896742e66dfaSMatthew G. Knepley } 89689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 89699371c9d4SSatish Balay if (p != pp) { 89709371c9d4SSatish Balay storagecheck = PETSC_FALSE; 89719371c9d4SSatish Balay continue; 89729371c9d4SSatish Balay } 89739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 89749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 8975ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 89769566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 89779566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 8978ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 89799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 89809371c9d4SSatish Balay if (cone[c] != pp) { 89819371c9d4SSatish Balay c = 0; 89829371c9d4SSatish Balay break; 89839371c9d4SSatish Balay } 8984ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 8985ca8062c8SMatthew G. Knepley } 8986ca8062c8SMatthew G. Knepley if (c >= coneSize) { 898763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 898848a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 89899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 899063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 899148a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 89929566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 899363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 8994ca8062c8SMatthew G. Knepley } 8995ca8062c8SMatthew G. Knepley } 8996ca8062c8SMatthew G. Knepley } 899757beb4faSStefano Zampini if (storagecheck) { 89989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 89999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 900063a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 900157beb4faSStefano Zampini } 90023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9003ca8062c8SMatthew G. Knepley } 9004ca8062c8SMatthew G. Knepley 9005412e9a14SMatthew G. Knepley /* 9006412e9a14SMatthew 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. 9007412e9a14SMatthew G. Knepley */ 9008d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9009d71ae5a4SJacob Faibussowitsch { 9010412e9a14SMatthew G. Knepley DMPolytopeType cct; 9011412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9012412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9013412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9014412e9a14SMatthew G. Knepley 9015412e9a14SMatthew G. Knepley PetscFunctionBegin; 9016412e9a14SMatthew G. Knepley *unsplit = 0; 9017412e9a14SMatthew G. Knepley switch (ct) { 9018d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9019d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9020d71ae5a4SJacob Faibussowitsch break; 9021412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 90229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90239566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9024412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9026412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9027412e9a14SMatthew G. Knepley } 9028412e9a14SMatthew G. Knepley break; 9029412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9030412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 90319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 90329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9033412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 90349566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 90359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9036412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 90379566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9038412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9039412e9a14SMatthew G. Knepley PetscInt p; 90409371c9d4SSatish Balay for (p = 0; p < npt; ++p) 90419371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9042412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9043412e9a14SMatthew G. Knepley } 9044412e9a14SMatthew G. Knepley } 9045412e9a14SMatthew G. Knepley } 9046412e9a14SMatthew G. Knepley break; 9047d71ae5a4SJacob Faibussowitsch default: 9048d71ae5a4SJacob Faibussowitsch break; 9049412e9a14SMatthew G. Knepley } 9050412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 90519566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9052412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9053412e9a14SMatthew G. Knepley } 90543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9055412e9a14SMatthew G. Knepley } 9056412e9a14SMatthew G. Knepley 9057ca8062c8SMatthew G. Knepley /*@ 9058ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9059ca8062c8SMatthew G. Knepley 9060ca8062c8SMatthew G. Knepley Input Parameters: 9061a1cb98faSBarry Smith + dm - The `DMPLEX` object 906258723a97SMatthew G. Knepley - cellHeight - Normally 0 9063ca8062c8SMatthew G. Knepley 9064a1cb98faSBarry Smith Level: developer 9065a1cb98faSBarry Smith 906695eb5ee5SVaclav Hapla Notes: 906795eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 906825c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9069ca8062c8SMatthew G. Knepley 907020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 907195eb5ee5SVaclav Hapla 90721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9073ca8062c8SMatthew G. Knepley @*/ 9074d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9075d71ae5a4SJacob Faibussowitsch { 9076412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9077412e9a14SMatthew G. Knepley DMPolytopeType ct; 9078412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9079ca8062c8SMatthew G. Knepley 9080ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9081ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90829566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 90839566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 90849566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9085412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9086412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9087412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 908858723a97SMatthew G. Knepley 90899566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 909063a3b9bcSJacob Faibussowitsch PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c); 9091412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9092412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 90939566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 909463a3b9bcSJacob 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)); 9095412e9a14SMatthew G. Knepley } 90969566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 909758723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 909858723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9099412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 910058723a97SMatthew G. Knepley } 91019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9102412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9103412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9104412e9a14SMatthew G. Knepley PetscInt unsplit; 910542363296SMatthew G. Knepley 91069566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9107412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 910842363296SMatthew G. Knepley } 910963a3b9bcSJacob 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)); 911042363296SMatthew G. Knepley } 91113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9112ca8062c8SMatthew G. Knepley } 91139bf0dad6SMatthew G. Knepley 91149bf0dad6SMatthew G. Knepley /*@ 91159bf0dad6SMatthew 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 91169bf0dad6SMatthew G. Knepley 911720f4b53cSBarry Smith Collective 9118899ea2b8SJacob Faibussowitsch 91199bf0dad6SMatthew G. Knepley Input Parameters: 9120a1cb98faSBarry Smith + dm - The `DMPLEX` object 91219bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 91229bf0dad6SMatthew G. Knepley 9123a1cb98faSBarry Smith Level: developer 9124a1cb98faSBarry Smith 912545da879fSVaclav Hapla Notes: 912645da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 912745da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 912845da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 912945da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 91309bf0dad6SMatthew G. Knepley 9131a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 913295eb5ee5SVaclav Hapla 91331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 91349bf0dad6SMatthew G. Knepley @*/ 9135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9136d71ae5a4SJacob Faibussowitsch { 9137ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9138899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 91399bf0dad6SMatthew G. Knepley 91409bf0dad6SMatthew G. Knepley PetscFunctionBegin; 91419bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91428f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 91433ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 91448f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 91453ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 91463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9147899ea2b8SJacob Faibussowitsch } 9148899ea2b8SJacob Faibussowitsch 91499566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 91509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 91519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9152ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 91539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 91543554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9155412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9156412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9157ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9158412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9159412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 91609bf0dad6SMatthew G. Knepley 91619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 91629566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9163412e9a14SMatthew G. Knepley if (unsplit) continue; 91649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 91659566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 91669566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 91679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 91689bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 91699bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 91709bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 91719bf0dad6SMatthew G. Knepley } 91729566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 917363a3b9bcSJacob 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); 91749bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9175d4961f80SStefano Zampini DMPolytopeType fct; 91769bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 91779bf0dad6SMatthew G. Knepley 91789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 91799566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 91809bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 91819bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 91829bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 91839bf0dad6SMatthew G. Knepley } 918463a3b9bcSJacob 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]); 91859bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9186b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9187b5a892a1SMatthew G. Knepley PetscInt v1; 9188b5a892a1SMatthew G. Knepley 91899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 919063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 91919566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 919263a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 91939566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 919463a3b9bcSJacob 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]); 9195b5a892a1SMatthew G. Knepley } 91969bf0dad6SMatthew G. Knepley } 91979566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9198412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 91999bf0dad6SMatthew G. Knepley } 92009566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 92019566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 92029bf0dad6SMatthew G. Knepley } 92033554e41dSMatthew G. Knepley } 92043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9205552f7358SJed Brown } 92063913d7c8SMatthew G. Knepley 9207bb6a34a8SMatthew G. Knepley /*@ 9208bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9209bb6a34a8SMatthew G. Knepley 9210bb6a34a8SMatthew G. Knepley Input Parameter: 9211a1cb98faSBarry Smith . dm - The `DMPLEX` object 9212a1cb98faSBarry Smith 9213a1cb98faSBarry Smith Level: developer 9214bb6a34a8SMatthew G. Knepley 921595eb5ee5SVaclav Hapla Notes: 921695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 921795eb5ee5SVaclav Hapla 921820f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9219bb6a34a8SMatthew G. Knepley 92201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9221bb6a34a8SMatthew G. Knepley @*/ 9222d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9223d71ae5a4SJacob Faibussowitsch { 9224a2a9e04cSMatthew G. Knepley Vec coordinates; 9225bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9226bb6a34a8SMatthew G. Knepley PetscReal vol; 922751a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9228bb6a34a8SMatthew G. Knepley 9229bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 92309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 92319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 92323ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 92339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9234bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 92359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9236a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 92379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 92383ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9239412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9240412e9a14SMatthew G. Knepley DMPolytopeType ct; 9241412e9a14SMatthew G. Knepley PetscInt unsplit; 9242412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9243412e9a14SMatthew G. Knepley 92449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9245412e9a14SMatthew G. Knepley switch (ct) { 9246412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9247412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9248d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9249d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9250d71ae5a4SJacob Faibussowitsch break; 9251d71ae5a4SJacob Faibussowitsch default: 9252d71ae5a4SJacob Faibussowitsch break; 9253412e9a14SMatthew G. Knepley } 9254412e9a14SMatthew G. Knepley switch (ct) { 9255412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9256412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9257412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9258d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9259d71ae5a4SJacob Faibussowitsch continue; 9260d71ae5a4SJacob Faibussowitsch default: 9261d71ae5a4SJacob Faibussowitsch break; 9262412e9a14SMatthew G. Knepley } 92639566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9264412e9a14SMatthew G. Knepley if (unsplit) continue; 92659566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 92661dca8a05SBarry 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); 926763a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 92686858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 92696858538eSMatthew G. Knepley if (depth > 1) { 92709566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 92711dca8a05SBarry 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); 927263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9273bb6a34a8SMatthew G. Knepley } 9274bb6a34a8SMatthew G. Knepley } 92753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9276bb6a34a8SMatthew G. Knepley } 9277bb6a34a8SMatthew G. Knepley 927803da9461SVaclav Hapla /*@ 927920f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 92807726db96SVaclav Hapla 928120f4b53cSBarry Smith Collective 928203da9461SVaclav Hapla 928303da9461SVaclav Hapla Input Parameters: 9284a1cb98faSBarry Smith + dm - The `DMPLEX` object 928520f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9286a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9287a1cb98faSBarry Smith 9288a1cb98faSBarry Smith Level: developer 928903da9461SVaclav Hapla 9290e83a0d2dSVaclav Hapla Notes: 9291e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 929203da9461SVaclav Hapla 9293a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 929495eb5ee5SVaclav Hapla 9295baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9296d7d32a9aSMatthew G. Knepley 92971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 929803da9461SVaclav Hapla @*/ 9299d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9300d71ae5a4SJacob Faibussowitsch { 93017726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 93027726db96SVaclav Hapla const PetscInt *locals; 93037726db96SVaclav Hapla const PetscSFNode *remotes; 9304f0cfc026SVaclav Hapla PetscBool distributed; 93057726db96SVaclav Hapla MPI_Comm comm; 93067726db96SVaclav Hapla PetscMPIInt rank; 930703da9461SVaclav Hapla 930803da9461SVaclav Hapla PetscFunctionBegin; 930903da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93107726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 93117726db96SVaclav Hapla else pointSF = dm->sf; 93127726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 93137726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 93147726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 93157726db96SVaclav Hapla { 93167726db96SVaclav Hapla PetscMPIInt mpiFlag; 93177726db96SVaclav Hapla 93187726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 93197726db96SVaclav 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); 93207726db96SVaclav Hapla } 93217726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 93229566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 93237726db96SVaclav Hapla if (!distributed) { 93247726db96SVaclav 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); 93253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 93268918e3e2SVaclav Hapla } 93277726db96SVaclav 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); 93287726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 932903da9461SVaclav Hapla 93307726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 93317726db96SVaclav Hapla { 93327726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 93337726db96SVaclav Hapla 93347726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 93357726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9336d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 93377726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 93387726db96SVaclav Hapla } 93397726db96SVaclav Hapla 93407726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 93417726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 93427726db96SVaclav 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); 93437726db96SVaclav Hapla } 93447726db96SVaclav Hapla 93457726db96SVaclav Hapla /* Check there are no cells in interface */ 93467726db96SVaclav Hapla if (!overlap) { 93477726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 93487726db96SVaclav Hapla 93499566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 93509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9351f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93527726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9353f5869d18SMatthew G. Knepley 93547726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 93557726db96SVaclav Hapla } 935603da9461SVaclav Hapla } 9357ece87651SVaclav Hapla 93587726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 93597726db96SVaclav Hapla { 93607726db96SVaclav Hapla const PetscInt *rootdegree; 93617726db96SVaclav Hapla 93627726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 93637726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9364f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 93657726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9366f5869d18SMatthew G. Knepley const PetscInt *cone; 9367f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9368f5869d18SMatthew G. Knepley 93699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 93709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9371f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9372f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 93737726db96SVaclav Hapla if (locals) { 93749566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 93757726db96SVaclav Hapla } else { 93767726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 93777726db96SVaclav Hapla } 937863a3b9bcSJacob 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]); 9379f5869d18SMatthew G. Knepley } 9380f5869d18SMatthew G. Knepley } 9381ece87651SVaclav Hapla } 93827726db96SVaclav Hapla } 93833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 938403da9461SVaclav Hapla } 938503da9461SVaclav Hapla 93867f9d8d6cSVaclav Hapla /*@ 938720f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 93887f9d8d6cSVaclav Hapla 93897f9d8d6cSVaclav Hapla Input Parameter: 9390a1cb98faSBarry Smith . dm - The `DMPLEX` object 9391a1cb98faSBarry Smith 9392a1cb98faSBarry Smith Level: developer 93937f9d8d6cSVaclav Hapla 93947f9d8d6cSVaclav Hapla Notes: 93957f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 93967f9d8d6cSVaclav Hapla 939720f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 93987f9d8d6cSVaclav Hapla 939920f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 94007f9d8d6cSVaclav Hapla 94011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 94027f9d8d6cSVaclav Hapla @*/ 9403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9404d71ae5a4SJacob Faibussowitsch { 94057f9d8d6cSVaclav Hapla PetscInt cellHeight; 94067f9d8d6cSVaclav Hapla 9407b5a892a1SMatthew G. Knepley PetscFunctionBegin; 94087f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 94099566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 94109566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 94119566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 94129566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9413d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 94149566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 94153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9416b5a892a1SMatthew G. Knepley } 9417b5a892a1SMatthew G. Knepley 94189371c9d4SSatish Balay typedef struct cell_stats { 9419068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9420068a5610SStefano Zampini PetscInt count; 9421068a5610SStefano Zampini } cell_stats_t; 9422068a5610SStefano Zampini 9423d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9424d71ae5a4SJacob Faibussowitsch { 9425068a5610SStefano Zampini PetscInt i, N = *len; 9426068a5610SStefano Zampini 9427068a5610SStefano Zampini for (i = 0; i < N; i++) { 9428068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9429068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9430068a5610SStefano Zampini 9431068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9432068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9433068a5610SStefano Zampini B->sum += A->sum; 9434068a5610SStefano Zampini B->squaresum += A->squaresum; 9435068a5610SStefano Zampini B->count += A->count; 9436068a5610SStefano Zampini } 9437068a5610SStefano Zampini } 9438068a5610SStefano Zampini 9439068a5610SStefano Zampini /*@ 944043fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9441068a5610SStefano Zampini 944220f4b53cSBarry Smith Collective 94438261a58bSMatthew G. Knepley 9444068a5610SStefano Zampini Input Parameters: 9445a1cb98faSBarry Smith + dm - The `DMPLEX` object 944620f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9447a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9448a1cb98faSBarry Smith 9449a1cb98faSBarry Smith Level: developer 9450068a5610SStefano Zampini 945195eb5ee5SVaclav Hapla Notes: 945295eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 945395eb5ee5SVaclav Hapla 9454a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9455068a5610SStefano Zampini 94561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9457068a5610SStefano Zampini @*/ 9458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9459d71ae5a4SJacob Faibussowitsch { 9460068a5610SStefano Zampini DM dmCoarse; 946143fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 946243fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 946343fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 946443fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9465412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 946643fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9467068a5610SStefano Zampini 9468068a5610SStefano Zampini PetscFunctionBegin; 9469068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9470068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9471068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9472068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9473068a5610SStefano Zampini stats.count = 0; 9474068a5610SStefano Zampini 94759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 94769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 94779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 94789566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 94799566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 94809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9481412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9482068a5610SStefano Zampini PetscInt i; 9483068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9484068a5610SStefano Zampini 94859566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 948663a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 948743fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9488068a5610SStefano Zampini frobJ += J[i] * J[i]; 9489068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9490068a5610SStefano Zampini } 9491068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9492068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9493068a5610SStefano Zampini 9494068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9495068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9496068a5610SStefano Zampini stats.sum += cond; 9497068a5610SStefano Zampini stats.squaresum += cond2; 9498068a5610SStefano Zampini stats.count++; 94998261a58bSMatthew G. Knepley if (output && cond > limit) { 950043fa8764SMatthew G. Knepley PetscSection coordSection; 950143fa8764SMatthew G. Knepley Vec coordsLocal; 950243fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 950343fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 950443fa8764SMatthew G. Knepley 95059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 95069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 95079566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 950863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 950943fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 951063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 951143fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 95129566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 95139566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 951443fa8764SMatthew G. Knepley } 95159566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 951643fa8764SMatthew G. Knepley } 95179566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 951843fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 951943fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 952043fa8764SMatthew G. Knepley 952143fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 952243fa8764SMatthew G. Knepley PetscReal len; 952343fa8764SMatthew G. Knepley 95249566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 952563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 952643fa8764SMatthew G. Knepley } 952743fa8764SMatthew G. Knepley } 95289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 95299566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 953043fa8764SMatthew G. Knepley } 9531068a5610SStefano Zampini } 95329566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9533068a5610SStefano Zampini 9534068a5610SStefano Zampini if (size > 1) { 9535068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9536068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9537068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9538068a5610SStefano Zampini MPI_Op statReduce; 9539068a5610SStefano Zampini 95409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 95419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 95429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 95439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 95449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 95459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9546068a5610SStefano Zampini } else { 95479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9548068a5610SStefano Zampini } 9549dd400576SPatrick Sanan if (rank == 0) { 9550068a5610SStefano Zampini count = globalStats.count; 9551068a5610SStefano Zampini min = globalStats.min; 9552068a5610SStefano Zampini max = globalStats.max; 9553068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9554068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9555068a5610SStefano Zampini } 9556068a5610SStefano Zampini 955748a46eb9SPierre 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)); 95589566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9559068a5610SStefano Zampini 95609566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9561068a5610SStefano Zampini if (dmCoarse) { 9562068a5610SStefano Zampini PetscBool isplex; 9563068a5610SStefano Zampini 95649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 95651baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9566068a5610SStefano Zampini } 95673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9568068a5610SStefano Zampini } 9569068a5610SStefano Zampini 9570f108dbd7SJacob Faibussowitsch /*@ 9571f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9572f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9573f108dbd7SJacob Faibussowitsch 957420f4b53cSBarry Smith Collective 9575f108dbd7SJacob Faibussowitsch 9576f108dbd7SJacob Faibussowitsch Input Parameters: 9577a1cb98faSBarry Smith + dm - The `DMPLEX` object 9578a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9579f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9580f108dbd7SJacob Faibussowitsch 9581f108dbd7SJacob Faibussowitsch Output Parameters: 958220f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9583a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9584f108dbd7SJacob Faibussowitsch 9585f108dbd7SJacob Faibussowitsch Options Database Keys: 9586a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9587f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9588f108dbd7SJacob Faibussowitsch 9589a1cb98faSBarry Smith Level: intermediate 9590a1cb98faSBarry Smith 9591f108dbd7SJacob Faibussowitsch Notes: 9592a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9593f108dbd7SJacob Faibussowitsch 9594a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9595f108dbd7SJacob Faibussowitsch 9596f108dbd7SJacob 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 9597f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9598f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9599f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9600f108dbd7SJacob Faibussowitsch 9601f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9602f108dbd7SJacob Faibussowitsch 9603a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9604f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9605f108dbd7SJacob Faibussowitsch 9606f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9607f108dbd7SJacob Faibussowitsch 96081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9609f108dbd7SJacob Faibussowitsch @*/ 9610d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9611d71ae5a4SJacob Faibussowitsch { 96126ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 96136ed19f2fSJacob Faibussowitsch PetscInt *idx; 96146ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9615f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 96166ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9617f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9618f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9619f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9620f108dbd7SJacob Faibussowitsch IS glob; 9621f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9622f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9623f108dbd7SJacob Faibussowitsch 9624f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9625f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9626ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 96274f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 96286bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 96299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 96309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 963163a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 96326ed19f2fSJacob Faibussowitsch { 96336ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 96346ed19f2fSJacob Faibussowitsch 96359566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9636f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9637f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9638f108dbd7SJacob Faibussowitsch 96399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 964098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9641f108dbd7SJacob Faibussowitsch } 96426ed19f2fSJacob Faibussowitsch } 9643f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 96444f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 96459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 96469566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 96479371c9d4SSatish Balay } else { 96489371c9d4SSatish Balay *OrthQualLabel = NULL; 96499371c9d4SSatish Balay } 96509566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 96519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 96529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob)); 96539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 96549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 96559566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 96569566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 96579566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 96589566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 96599566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 96609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 96619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 96629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 96639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 96649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 96659566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 96669566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 96679566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 96686ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 96696ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9670f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9671f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9672898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9673f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9674f108dbd7SJacob Faibussowitsch 96756ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9676f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9677f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 96789566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 96799566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9680f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 96819566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 96826ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 96836ed19f2fSJacob Faibussowitsch PetscInt i; 96846ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9685f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9686f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9687f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9688f108dbd7SJacob Faibussowitsch 9689f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9690f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 96919566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9692f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 96936ed19f2fSJacob Faibussowitsch { 96946ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 96956ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 96966ed19f2fSJacob Faibussowitsch 96979566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 96989566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 96999566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 97006ed19f2fSJacob Faibussowitsch } 9701f108dbd7SJacob Faibussowitsch 9702f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9703f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9704f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9705f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9706f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9707addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9708addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9709addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9710f108dbd7SJacob Faibussowitsch } 9711addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9712addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9713addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9714f108dbd7SJacob Faibussowitsch 9715f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9716f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9717f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9718f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9719f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9720f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9721f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9722f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9723f108dbd7SJacob Faibussowitsch } 9724ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9725ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9726f108dbd7SJacob Faibussowitsch } 97279566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 97289566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9729f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 97306ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9731f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97329566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9733f108dbd7SJacob Faibussowitsch } 9734f108dbd7SJacob Faibussowitsch } 97359566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 97369566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 97379566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 97389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 97399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 97409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9741f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 97429566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9743f108dbd7SJacob Faibussowitsch } 97449566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9745cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&vwr)); 97469566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 97473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9748f108dbd7SJacob Faibussowitsch } 9749f108dbd7SJacob Faibussowitsch 9750d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 97511eb70e55SToby Isaac * interpolator construction */ 9752d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9753d71ae5a4SJacob Faibussowitsch { 97541eb70e55SToby Isaac PetscSection section, newSection, gsection; 97551eb70e55SToby Isaac PetscSF sf; 97561eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 97571eb70e55SToby Isaac 97581eb70e55SToby Isaac PetscFunctionBegin; 97591eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 97604f572ea9SToby Isaac PetscAssertPointer(odm, 2); 97619566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 97629566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9763712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 97641eb70e55SToby Isaac if (!ghasConstraints) { 97659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 97661eb70e55SToby Isaac *odm = dm; 97673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97681eb70e55SToby Isaac } 97699566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 97709566063dSJacob Faibussowitsch PetscCall(DMCopyFields(dm, *odm)); 97719566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 97729566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 97739566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection)); 97749566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 97759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 97763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 97771eb70e55SToby Isaac } 97781eb70e55SToby Isaac 9779d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 9780d71ae5a4SJacob Faibussowitsch { 97811eb70e55SToby Isaac DM dmco, dmfo; 97821eb70e55SToby Isaac Mat interpo; 97831eb70e55SToby Isaac Vec rscale; 97841eb70e55SToby Isaac Vec cglobalo, clocal; 97851eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 97861eb70e55SToby Isaac PetscBool regular; 97871eb70e55SToby Isaac 97881eb70e55SToby Isaac PetscFunctionBegin; 97899566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 97909566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 97919566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 97929566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 97939566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 97949566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 97959566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 97969566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 97979566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 97989566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 97999566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 98009566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 98019566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 98029566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 98039566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 98049566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 98059566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 98069566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 98079566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 98089566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 98099566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 98109566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 98119566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 98129566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 98131eb70e55SToby Isaac *shift = fglobal; 98149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 98159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 98169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 98179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 98189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 98209566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 98219566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 98223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98231eb70e55SToby Isaac } 98241eb70e55SToby Isaac 9825d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 9826d71ae5a4SJacob Faibussowitsch { 98271eb70e55SToby Isaac PetscObject shifto; 98281eb70e55SToby Isaac Vec shift; 98291eb70e55SToby Isaac 98301eb70e55SToby Isaac PetscFunctionBegin; 98311eb70e55SToby Isaac if (!interp) { 98321eb70e55SToby Isaac Vec rscale; 98331eb70e55SToby Isaac 98349566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 98359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 98361eb70e55SToby Isaac } else { 98379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 98381eb70e55SToby Isaac } 98399566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 98401eb70e55SToby Isaac if (!shifto) { 98419566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 98429566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 98431eb70e55SToby Isaac shifto = (PetscObject)shift; 98449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 98451eb70e55SToby Isaac } 98461eb70e55SToby Isaac shift = (Vec)shifto; 98479566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 98489566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 98499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 98503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98511eb70e55SToby Isaac } 98521eb70e55SToby Isaac 9853bceba477SMatthew G. Knepley /* Pointwise interpolation 9854bceba477SMatthew G. Knepley Just code FEM for now 9855bceba477SMatthew G. Knepley u^f = I u^c 98564ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 98574ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 98584ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 9859bceba477SMatthew G. Knepley */ 9860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 9861d71ae5a4SJacob Faibussowitsch { 9862bceba477SMatthew G. Knepley PetscSection gsc, gsf; 9863bceba477SMatthew G. Knepley PetscInt m, n; 9864a063dac3SMatthew G. Knepley void *ctx; 986568132eb9SMatthew G. Knepley DM cdm; 9866cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 9867bceba477SMatthew G. Knepley 9868bceba477SMatthew G. Knepley PetscFunctionBegin; 98699566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 98709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 98719566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 98729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 987368132eb9SMatthew G. Knepley 98749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 98759566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 98769566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 98779566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 98789566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 987968132eb9SMatthew G. Knepley 98809566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 98819566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 98829566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 98839566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 98849566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 98854db47ee9SStefano Zampini if (scaling) { 98865d1c2e58SMatthew G. Knepley /* Use naive scaling */ 98879566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 98884db47ee9SStefano Zampini } 98893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9890a063dac3SMatthew G. Knepley } 9891bceba477SMatthew G. Knepley 9892d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 9893d71ae5a4SJacob Faibussowitsch { 98946dbf9973SLawrence Mitchell VecScatter ctx; 989590748bafSMatthew G. Knepley 9896a063dac3SMatthew G. Knepley PetscFunctionBegin; 98979566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 98989566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 98999566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 99003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9901bceba477SMatthew G. Knepley } 9902bceba477SMatthew G. Knepley 9903d71ae5a4SJacob 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[]) 9904d71ae5a4SJacob Faibussowitsch { 990500635df3SMatthew G. Knepley const PetscInt Nc = uOff[1] - uOff[0]; 990600635df3SMatthew G. Knepley PetscInt c; 990700635df3SMatthew G. Knepley for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 99083e9753d6SMatthew G. Knepley } 99093e9753d6SMatthew G. Knepley 9910d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) 9911d71ae5a4SJacob Faibussowitsch { 9912b4937a87SMatthew G. Knepley DM dmc; 9913b4937a87SMatthew G. Knepley PetscDS ds; 9914b4937a87SMatthew G. Knepley Vec ones, locmass; 9915b4937a87SMatthew G. Knepley IS cellIS; 9916b4937a87SMatthew G. Knepley PetscFormKey key; 9917b4937a87SMatthew G. Knepley PetscInt depth; 9918b4937a87SMatthew G. Knepley 9919b4937a87SMatthew G. Knepley PetscFunctionBegin; 99209566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 99219566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 99229566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99239566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99249566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmc, mass)); 99259566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &ones)); 99269566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dmc, &locmass)); 99279566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99289566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99299566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 99309566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 9931b4937a87SMatthew G. Knepley key.label = NULL; 9932b4937a87SMatthew G. Knepley key.value = 0; 9933b4937a87SMatthew G. Knepley key.field = 0; 9934b4937a87SMatthew G. Knepley key.part = 0; 99359566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 99369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99379566063dSJacob Faibussowitsch PetscCall(VecSet(*mass, 0.0)); 99389566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass)); 99399566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass)); 99409566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &ones)); 99419566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dmc, &locmass)); 99429566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9944b4937a87SMatthew G. Knepley } 9945b4937a87SMatthew G. Knepley 9946d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 9947d71ae5a4SJacob Faibussowitsch { 9948bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 9949bd041c0cSMatthew G. Knepley PetscInt m, n; 9950bd041c0cSMatthew G. Knepley void *ctx; 9951bd041c0cSMatthew G. Knepley DM cdm; 9952bd041c0cSMatthew G. Knepley PetscBool regular; 9953bd041c0cSMatthew G. Knepley 9954bd041c0cSMatthew G. Knepley PetscFunctionBegin; 99553e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 99563e9753d6SMatthew G. Knepley DM dmc; 99573e9753d6SMatthew G. Knepley PetscDS ds; 9958b4937a87SMatthew G. Knepley PetscWeakForm wf; 99593e9753d6SMatthew G. Knepley Vec u; 99603e9753d6SMatthew G. Knepley IS cellIS; 996106ad1575SMatthew G. Knepley PetscFormKey key; 99623e9753d6SMatthew G. Knepley PetscInt depth; 99633e9753d6SMatthew G. Knepley 99649566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 99659566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 99669566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 99679566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 99689566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 99699566063dSJacob Faibussowitsch PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL)); 99709566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 99718d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 99729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 99739566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 99749566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 99756528b96dSMatthew G. Knepley key.label = NULL; 99766528b96dSMatthew G. Knepley key.value = 0; 99776528b96dSMatthew G. Knepley key.field = 0; 997806ad1575SMatthew G. Knepley key.part = 0; 99799566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 99809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 99818d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 99829566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 99833e9753d6SMatthew G. Knepley } else { 99849566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 99859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 99869566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 99879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 9988bd041c0cSMatthew G. Knepley 99899566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 99909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 99919566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 99929566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9993bd041c0cSMatthew G. Knepley 99949566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 99959566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 99969566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 99979566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 99983e9753d6SMatthew G. Knepley } 99999566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 100003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10001bd041c0cSMatthew G. Knepley } 10002bd041c0cSMatthew G. Knepley 100030aef6b92SMatthew G. Knepley /*@ 100040aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100050aef6b92SMatthew G. Knepley 100060aef6b92SMatthew G. Knepley Input Parameter: 10007a1cb98faSBarry Smith . dm - The `DMPLEX` object 100080aef6b92SMatthew G. Knepley 100090aef6b92SMatthew G. Knepley Output Parameter: 100100aef6b92SMatthew G. Knepley . regular - The flag 100110aef6b92SMatthew G. Knepley 100120aef6b92SMatthew G. Knepley Level: intermediate 100130aef6b92SMatthew G. Knepley 100141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 100150aef6b92SMatthew G. Knepley @*/ 10016d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10017d71ae5a4SJacob Faibussowitsch { 100180aef6b92SMatthew G. Knepley PetscFunctionBegin; 100190aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100204f572ea9SToby Isaac PetscAssertPointer(regular, 2); 100210aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 100223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100230aef6b92SMatthew G. Knepley } 100240aef6b92SMatthew G. Knepley 100250aef6b92SMatthew G. Knepley /*@ 100260aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 100270aef6b92SMatthew G. Knepley 100280aef6b92SMatthew G. Knepley Input Parameters: 10029a1cb98faSBarry Smith + dm - The `DMPLEX` object 100300aef6b92SMatthew G. Knepley - regular - The flag 100310aef6b92SMatthew G. Knepley 100320aef6b92SMatthew G. Knepley Level: intermediate 100330aef6b92SMatthew G. Knepley 100341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 100350aef6b92SMatthew G. Knepley @*/ 10036d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10037d71ae5a4SJacob Faibussowitsch { 100380aef6b92SMatthew G. Knepley PetscFunctionBegin; 100390aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100400aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 100413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100420aef6b92SMatthew G. Knepley } 100430aef6b92SMatthew G. Knepley 10044a68b90caSToby Isaac /*@ 10045f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10046a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10047a68b90caSToby Isaac 10048a1cb98faSBarry Smith Not Collective 10049a68b90caSToby Isaac 10050f899ff85SJose E. Roman Input Parameter: 10051a1cb98faSBarry Smith . dm - The `DMPLEX` object 10052a68b90caSToby Isaac 10053a68b90caSToby Isaac Output Parameters: 1005420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1005520f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10056a68b90caSToby Isaac 10057a68b90caSToby Isaac Level: intermediate 10058a68b90caSToby Isaac 100591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10060a68b90caSToby Isaac @*/ 10061d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10062d71ae5a4SJacob Faibussowitsch { 10063a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10064a68b90caSToby Isaac 10065a68b90caSToby Isaac PetscFunctionBegin; 10066a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100679566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10068a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10069a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 100703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10071a68b90caSToby Isaac } 10072a68b90caSToby Isaac 10073a68b90caSToby Isaac /*@ 10074a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10075a68b90caSToby Isaac 1007620f4b53cSBarry Smith Collective 10077a68b90caSToby Isaac 10078a68b90caSToby Isaac Input Parameters: 10079a1cb98faSBarry Smith + dm - The `DMPLEX` object 10080a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10081a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10082a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10083a68b90caSToby Isaac 10084a68b90caSToby Isaac Level: intermediate 10085a68b90caSToby Isaac 10086a1cb98faSBarry Smith Notes: 10087a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10088a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10089a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10090a4e35b19SJacob Faibussowitsch 10091a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10092a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10093a1cb98faSBarry Smith 1009420f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10095a1cb98faSBarry Smith 100961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10097a68b90caSToby Isaac @*/ 10098d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10099d71ae5a4SJacob Faibussowitsch { 10100a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10101e228b242SToby Isaac PetscMPIInt result; 10102a68b90caSToby Isaac 10103a68b90caSToby Isaac PetscFunctionBegin; 10104a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10105e228b242SToby Isaac if (anchorSection) { 10106e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 101079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 101081dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10109e228b242SToby Isaac } 10110e228b242SToby Isaac if (anchorIS) { 10111e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 101129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 101131dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10114e228b242SToby Isaac } 10115a68b90caSToby Isaac 101169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 101179566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10118a68b90caSToby Isaac plex->anchorSection = anchorSection; 10119a68b90caSToby Isaac 101209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 101219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10122a68b90caSToby Isaac plex->anchorIS = anchorIS; 10123a68b90caSToby Isaac 10124cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10125a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10126a68b90caSToby Isaac const PetscInt *anchors; 10127a68b90caSToby Isaac 101289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 101309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10131a68b90caSToby Isaac for (a = 0; a < size; a++) { 10132a68b90caSToby Isaac PetscInt p; 10133a68b90caSToby Isaac 10134a68b90caSToby Isaac p = anchors[a]; 10135a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10136a68b90caSToby Isaac PetscInt dof; 10137a68b90caSToby Isaac 101389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10139a68b90caSToby Isaac if (dof) { 101409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1014163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10142a68b90caSToby Isaac } 10143a68b90caSToby Isaac } 10144a68b90caSToby Isaac } 101459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10146a68b90caSToby Isaac } 10147f7c74593SToby Isaac /* reset the generic constraints */ 101489566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 101493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10150a68b90caSToby Isaac } 10151a68b90caSToby Isaac 10152d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10153d71ae5a4SJacob Faibussowitsch { 10154f7c74593SToby Isaac PetscSection anchorSection; 101556995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10156a68b90caSToby Isaac 10157a68b90caSToby Isaac PetscFunctionBegin; 10158a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101599566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 101609566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 101619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 101626995de1eSToby Isaac if (numFields) { 10163719ab38cSToby Isaac PetscInt f; 101649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10165719ab38cSToby Isaac 10166719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10167719ab38cSToby Isaac PetscInt numComp; 10168719ab38cSToby Isaac 101699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 101709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10171719ab38cSToby Isaac } 101726995de1eSToby Isaac } 101739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 101749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 101756995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 101766995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 101776995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 101789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10179a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 101809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10181a68b90caSToby Isaac if (dof) { 101829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 101839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10184a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 101859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 101869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10187a68b90caSToby Isaac } 10188a68b90caSToby Isaac } 10189a68b90caSToby Isaac } 101909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 101919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 101923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10193a68b90caSToby Isaac } 10194a68b90caSToby Isaac 10195d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10196d71ae5a4SJacob Faibussowitsch { 10197f7c74593SToby Isaac PetscSection aSec; 10198ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 101990ac89760SToby Isaac const PetscInt *anchors; 102000ac89760SToby Isaac PetscInt numFields, f; 1020166ad2231SToby Isaac IS aIS; 10202e19f7ee6SMark Adams MatType mtype; 10203e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 102040ac89760SToby Isaac 102050ac89760SToby Isaac PetscFunctionBegin; 102060ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 102089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 102099566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 102109566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 102119566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 102129566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 102139566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 102149566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10215e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10216e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10217e19f7ee6SMark Adams else mtype = MATSEQAIJ; 102189566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 102199566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 102209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 102216995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 102229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 102239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 102249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 102250ac89760SToby Isaac i[0] = 0; 102269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 102270ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10228f19733c5SToby Isaac PetscInt rDof, rOff, r; 10229f19733c5SToby Isaac 102309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10231f19733c5SToby Isaac if (!rDof) continue; 102329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102330ac89760SToby Isaac if (numFields) { 102340ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102350ac89760SToby Isaac annz = 0; 10236f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10237f19733c5SToby Isaac a = anchors[rOff + r]; 10238ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102400ac89760SToby Isaac annz += aDof; 102410ac89760SToby Isaac } 102429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10244ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102450ac89760SToby Isaac } 102462f7452b8SBarry Smith } else { 102470ac89760SToby Isaac annz = 0; 102489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102490ac89760SToby Isaac for (q = 0; q < dof; q++) { 10250ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10251ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 102530ac89760SToby Isaac annz += aDof; 102540ac89760SToby Isaac } 102559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10257ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 102580ac89760SToby Isaac } 102590ac89760SToby Isaac } 102600ac89760SToby Isaac nnz = i[m]; 102619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 102620ac89760SToby Isaac offset = 0; 102630ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 102640ac89760SToby Isaac if (numFields) { 102650ac89760SToby Isaac for (f = 0; f < numFields; f++) { 102669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 102670ac89760SToby Isaac for (q = 0; q < dof; q++) { 102680ac89760SToby Isaac PetscInt rDof, rOff, r; 102699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102710ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102720ac89760SToby Isaac PetscInt s; 102730ac89760SToby Isaac 102740ac89760SToby Isaac a = anchors[rOff + r]; 10275ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 102779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10278ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102790ac89760SToby Isaac } 102800ac89760SToby Isaac } 102810ac89760SToby Isaac } 102822f7452b8SBarry Smith } else { 102839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 102840ac89760SToby Isaac for (q = 0; q < dof; q++) { 102850ac89760SToby Isaac PetscInt rDof, rOff, r; 102869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 102879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 102880ac89760SToby Isaac for (r = 0; r < rDof; r++) { 102890ac89760SToby Isaac PetscInt s; 102900ac89760SToby Isaac 102910ac89760SToby Isaac a = anchors[rOff + r]; 10292ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 102939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 102949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10295ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 102960ac89760SToby Isaac } 102970ac89760SToby Isaac } 102980ac89760SToby Isaac } 102990ac89760SToby Isaac } 103009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 103019566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 103029566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 103039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 103043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 103050ac89760SToby Isaac } 103060ac89760SToby Isaac 10307d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10308d71ae5a4SJacob Faibussowitsch { 10309f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10310f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1031166ad2231SToby Isaac Mat cMat; 1031266ad2231SToby Isaac 1031366ad2231SToby Isaac PetscFunctionBegin; 1031466ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103159566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1031666ad2231SToby Isaac if (anchorSection) { 1031744a7f3ddSMatthew G. Knepley PetscInt Nf; 10318e228b242SToby Isaac 103199566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 103209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 103219566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 103229566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 103239566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 103249566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 103259566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 103269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1032766ad2231SToby Isaac } 103283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1032966ad2231SToby Isaac } 10330a93c429eSMatthew G. Knepley 10331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10332d71ae5a4SJacob Faibussowitsch { 10333a93c429eSMatthew G. Knepley IS subis; 10334a93c429eSMatthew G. Knepley PetscSection section, subsection; 10335a93c429eSMatthew G. Knepley 10336a93c429eSMatthew G. Knepley PetscFunctionBegin; 103379566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1033828b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1033928b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10340a93c429eSMatthew G. Knepley /* Create subdomain */ 103419566063dSJacob Faibussowitsch PetscCall(DMPlexFilter(dm, label, value, subdm)); 10342a93c429eSMatthew G. Knepley /* Create submodel */ 103439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 103449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 103459566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 103469566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 103479566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10348a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10349a93c429eSMatthew G. Knepley if (is) { 10350a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10351a93c429eSMatthew G. Knepley IS spIS; 10352a93c429eSMatthew G. Knepley const PetscInt *spmap; 10353a93c429eSMatthew G. Knepley PetscInt *subIndices; 10354a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10355a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10356a93c429eSMatthew G. Knepley 103579566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 103589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 103599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 103609566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 103619566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 103629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10363a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10364a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10365a93c429eSMatthew G. Knepley 103669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10367a93c429eSMatthew G. Knepley if (gdof > 0) { 10368a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10369a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10370a93c429eSMatthew G. Knepley 103719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 103729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10373a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10374a93c429eSMatthew G. Knepley } 10375a93c429eSMatthew G. Knepley subSize += pSubSize; 10376a93c429eSMatthew G. Knepley if (pSubSize) { 10377a93c429eSMatthew G. Knepley if (bs < 0) { 10378a93c429eSMatthew G. Knepley bs = pSubSize; 10379a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10380a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10381a93c429eSMatthew G. Knepley bs = 1; 10382a93c429eSMatthew G. Knepley } 10383a93c429eSMatthew G. Knepley } 10384a93c429eSMatthew G. Knepley } 10385a93c429eSMatthew G. Knepley } 10386a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 103879371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 103889371c9d4SSatish Balay bsLocal[1] = bs; 103899566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 103909371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 103919371c9d4SSatish Balay bs = 1; 103929371c9d4SSatish Balay } else { 103939371c9d4SSatish Balay bs = bsMinMax[0]; 103949371c9d4SSatish Balay } 103959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10396a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10397a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10398a93c429eSMatthew G. Knepley 103999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10400a93c429eSMatthew G. Knepley if (gdof > 0) { 10401a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10402a93c429eSMatthew G. Knepley 104039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10404a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10405a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10406a93c429eSMatthew G. Knepley 10407a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10408a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 104099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 104109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10411a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10412a93c429eSMatthew G. Knepley } 104139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 104149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10415ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10416a93c429eSMatthew G. Knepley } 10417a93c429eSMatthew G. Knepley } 10418a93c429eSMatthew G. Knepley } 104199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 104209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10421a93c429eSMatthew G. Knepley if (bs > 1) { 10422a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10423a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10424a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10425a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 104269371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 104279371c9d4SSatish Balay set = 0; 104289371c9d4SSatish Balay break; 104299371c9d4SSatish Balay } 10430a93c429eSMatthew G. Knepley } 10431a93c429eSMatthew G. Knepley } 104329566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10433a93c429eSMatthew G. Knepley } 10434a93c429eSMatthew G. Knepley /* Attach nullspace */ 10435a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10436a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10437a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10438a93c429eSMatthew G. Knepley } 10439a93c429eSMatthew G. Knepley if (f < Nf) { 10440a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 104419566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 104426823f3c5SBlaise Bourdin 104439566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 104449566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10445a93c429eSMatthew G. Knepley } 10446a93c429eSMatthew G. Knepley } 104473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10448a93c429eSMatthew G. Knepley } 10449c0f0dcc3SMatthew G. Knepley 10450c0f0dcc3SMatthew G. Knepley /*@ 10451c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10452c0f0dcc3SMatthew G. Knepley 10453a1cb98faSBarry Smith Input Parameters: 10454a1cb98faSBarry Smith + dm - The `DM` 10455a1cb98faSBarry Smith - dummy - unused argument 10456a1cb98faSBarry Smith 10457a1cb98faSBarry Smith Options Database Key: 10458a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10459c0f0dcc3SMatthew G. Knepley 10460c0f0dcc3SMatthew G. Knepley Level: developer 10461c0f0dcc3SMatthew G. Knepley 104621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10463c0f0dcc3SMatthew G. Knepley @*/ 10464d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10465d71ae5a4SJacob Faibussowitsch { 10466b665b14eSToby Isaac PetscLogHandler default_handler; 10467b665b14eSToby Isaac 104682611ad71SToby Isaac PetscFunctionBegin; 104692611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10470b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10471b665b14eSToby Isaac if (default_handler) { 10472c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10473c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10474c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10475c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10476c0f0dcc3SMatthew G. Knepley const char *name; 10477c0f0dcc3SMatthew G. Knepley 104789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 104799566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 104809566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 104819566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10482b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10483c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10484c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10485c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1048663a3b9bcSJacob 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))); 104872611ad71SToby Isaac } else { 10488b665b14eSToby 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."); 104892611ad71SToby Isaac } 104903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10491c0f0dcc3SMatthew G. Knepley } 10492