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> 11c789d87fSToby Isaac #include <petscblaslapack.h> 12552f7358SJed Brown 13552f7358SJed Brown /* Logging support */ 1402f7d72cSksagiyam 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; 15172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate; 16552f7358SJed Brown 17f39ec787SMatthew G. Knepley PetscBool Plexcite = PETSC_FALSE; 18f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n" 19f39ec787SMatthew G. Knepley "title = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n" 20f39ec787SMatthew G. Knepley "author = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n" 21f39ec787SMatthew G. Knepley "journal = {SIAM Journal on Scientific Computing},\n" 22f39ec787SMatthew G. Knepley "volume = {38},\n" 23f39ec787SMatthew G. Knepley "number = {5},\n" 24f39ec787SMatthew G. Knepley "pages = {S143--S155},\n" 25f39ec787SMatthew G. Knepley "eprint = {http://arxiv.org/abs/1506.07749},\n" 26f39ec787SMatthew G. Knepley "doi = {10.1137/15M1026092},\n" 27f39ec787SMatthew G. Knepley "year = {2016},\n" 28f39ec787SMatthew G. Knepley "petsc_uses={DMPlex},\n}\n"; 29f39ec787SMatthew G. Knepley 305a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 31552f7358SJed Brown 32e5337592SStefano Zampini /*@ 339318fe57SMatthew G. Knepley DMPlexIsSimplex - Is the first cell in this mesh a simplex? 349318fe57SMatthew G. Knepley 359318fe57SMatthew G. Knepley Input Parameter: 36a1cb98faSBarry Smith . dm - The `DMPLEX` object 379318fe57SMatthew G. Knepley 389318fe57SMatthew G. Knepley Output Parameter: 399318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex 409318fe57SMatthew G. Knepley 419318fe57SMatthew G. Knepley Level: intermediate 429318fe57SMatthew G. Knepley 43a1cb98faSBarry Smith Note: 44a1cb98faSBarry Smith This just gives the first range of cells found. If the mesh has several cell types, it will only give the first. 45a1cb98faSBarry Smith If the mesh has no cells, this returns `PETSC_FALSE`. 46a1cb98faSBarry Smith 471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()` 489318fe57SMatthew G. Knepley @*/ 49d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) 50d71ae5a4SJacob Faibussowitsch { 519318fe57SMatthew G. Knepley DMPolytopeType ct; 529318fe57SMatthew G. Knepley PetscInt cStart, cEnd; 539318fe57SMatthew G. Knepley 549318fe57SMatthew G. Knepley PetscFunctionBegin; 559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 569371c9d4SSatish Balay if (cEnd <= cStart) { 579371c9d4SSatish Balay *simplex = PETSC_FALSE; 583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 599371c9d4SSatish Balay } 609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 619318fe57SMatthew G. Knepley *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 639318fe57SMatthew G. Knepley } 649318fe57SMatthew G. Knepley 659318fe57SMatthew G. Knepley /*@ 66412e9a14SMatthew G. Knepley DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells 67e5337592SStefano Zampini 68d8d19677SJose E. Roman Input Parameters: 69a1cb98faSBarry Smith + dm - The `DMPLEX` object 70412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default 71e5337592SStefano Zampini 72e5337592SStefano Zampini Output Parameters: 73412e9a14SMatthew G. Knepley + cStart - The first "normal" cell 7440196513SBarry Smith - cEnd - The upper bound on "normal" cells 75e5337592SStefano Zampini 76412e9a14SMatthew G. Knepley Level: developer 77e5337592SStefano Zampini 78a1cb98faSBarry Smith Note: 795ae96e2bSMatthew G. Knepley This function requires that tensor cells are ordered last. 80a1cb98faSBarry Smith 812827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()` 82e5337592SStefano Zampini @*/ 83d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) 84d71ae5a4SJacob Faibussowitsch { 855ae96e2bSMatthew G. Knepley DMLabel ctLabel; 865ae96e2bSMatthew G. Knepley IS valueIS; 875ae96e2bSMatthew G. Knepley const PetscInt *ctypes; 885e27db3eSMatthew G. Knepley PetscBool found = PETSC_FALSE; 895ae96e2bSMatthew G. Knepley PetscInt Nct, cS = PETSC_MAX_INT, cE = 0; 90e5337592SStefano Zampini 91e5337592SStefano Zampini PetscFunctionBegin; 929566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 935ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetValueIS(ctLabel, &valueIS)); 945ae96e2bSMatthew G. Knepley PetscCall(ISGetLocalSize(valueIS, &Nct)); 955ae96e2bSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &ctypes)); 965ae96e2bSMatthew G. Knepley for (PetscInt t = 0; t < Nct; ++t) { 97c306944fSJed Brown const DMPolytopeType ct = (DMPolytopeType)ctypes[t]; 985ae96e2bSMatthew G. Knepley PetscInt ctS, ctE, ht; 995ae96e2bSMatthew G. Knepley 1005ae96e2bSMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 1015ae96e2bSMatthew G. Knepley // If any cells are not typed, just use all cells 1025ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), cStart, cEnd)); 1035ae96e2bSMatthew G. Knepley break; 1045ae96e2bSMatthew G. Knepley } 105c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) || ct == DM_POLYTOPE_FV_GHOST) continue; 1065ae96e2bSMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &ctS, &ctE)); 1075ae96e2bSMatthew G. Knepley if (ctS >= ctE) continue; 1085ae96e2bSMatthew G. Knepley // Check that a point has the right height 1095ae96e2bSMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, ctS, &ht)); 1105ae96e2bSMatthew G. Knepley if (ht != height) continue; 1115ae96e2bSMatthew G. Knepley cS = PetscMin(cS, ctS); 1125ae96e2bSMatthew G. Knepley cE = PetscMax(cE, ctE); 1135e27db3eSMatthew G. Knepley found = PETSC_TRUE; 1145ae96e2bSMatthew G. Knepley } 1155e27db3eSMatthew G. Knepley if (!Nct || !found) cS = cE = 0; 1165ae96e2bSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 117695799ffSMatthew G. Knepley // Reset label for fast lookup 118695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel)); 119412e9a14SMatthew G. Knepley if (cStart) *cStart = cS; 120412e9a14SMatthew G. Knepley if (cEnd) *cEnd = cE; 1213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122e5337592SStefano Zampini } 123e5337592SStefano Zampini 1249c600e38SMatt McGurn PetscErrorCode DMPlexGetFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **ssStart, PetscInt **ssEnd, PetscViewerVTKFieldType **sft) 1259c600e38SMatt McGurn { 1269c600e38SMatt McGurn PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd, c, depth, cellHeight, t; 1279c600e38SMatt McGurn PetscInt *sStart, *sEnd; 1289c600e38SMatt McGurn PetscViewerVTKFieldType *ft; 1299c600e38SMatt McGurn PetscInt vcdof[DM_NUM_POLYTOPES + 1], globalvcdof[DM_NUM_POLYTOPES + 1]; 1309c600e38SMatt McGurn DMLabel depthLabel, ctLabel; 1319c600e38SMatt McGurn 1329c600e38SMatt McGurn PetscFunctionBegin; 1339c600e38SMatt McGurn /* the vcdof and globalvcdof are sized to allow every polytope type and simple vertex at DM_NUM_POLYTOPES */ 1349c600e38SMatt McGurn PetscCall(PetscArrayzero(vcdof, DM_NUM_POLYTOPES + 1)); 1359c600e38SMatt McGurn PetscCall(DMGetCoordinateDim(dm, &cdim)); 1369c600e38SMatt McGurn PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1379c600e38SMatt McGurn PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 1389c600e38SMatt McGurn if (field >= 0) { 1399c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[DM_NUM_POLYTOPES])); 1409c600e38SMatt McGurn } else { 1419c600e38SMatt McGurn if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[DM_NUM_POLYTOPES])); 1429c600e38SMatt McGurn } 1439c600e38SMatt McGurn 1449c600e38SMatt McGurn PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 1459c600e38SMatt McGurn PetscCall(DMPlexGetDepth(dm, &depth)); 1469c600e38SMatt McGurn PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 1479c600e38SMatt McGurn PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 1489c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1499c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1509c600e38SMatt McGurn PetscInt dep; 1519c600e38SMatt McGurn 1529c600e38SMatt McGurn if (ict == DM_POLYTOPE_FV_GHOST) continue; 1539c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1549c600e38SMatt McGurn if (pStart >= 0) { 1559c600e38SMatt McGurn PetscCall(DMLabelGetValue(depthLabel, cStart, &dep)); 1569c600e38SMatt McGurn if (dep != depth - cellHeight) continue; 1579c600e38SMatt McGurn } 1589c600e38SMatt McGurn if (field >= 0) { 1599c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[c])); 1609c600e38SMatt McGurn } else { 1619c600e38SMatt McGurn if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[c])); 1629c600e38SMatt McGurn } 1639c600e38SMatt McGurn } 1649c600e38SMatt McGurn 1659c600e38SMatt McGurn PetscCall(MPIU_Allreduce(vcdof, globalvcdof, DM_NUM_POLYTOPES + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 1669c600e38SMatt McGurn *types = 0; 1679c600e38SMatt McGurn 1689c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES + 1; ++c) { 1699c600e38SMatt McGurn if (globalvcdof[c]) ++(*types); 1709c600e38SMatt McGurn } 1719c600e38SMatt McGurn 1729c600e38SMatt McGurn PetscCall(PetscMalloc3(*types, &sStart, *types, &sEnd, *types, &ft)); 1739c600e38SMatt McGurn t = 0; 1749c600e38SMatt McGurn if (globalvcdof[DM_NUM_POLYTOPES]) { 1759c600e38SMatt McGurn sStart[t] = vStart; 1769c600e38SMatt McGurn sEnd[t] = vEnd; 1779c600e38SMatt McGurn ft[t] = (globalvcdof[t] == cdim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 1789c600e38SMatt McGurn ++t; 1799c600e38SMatt McGurn } 1809c600e38SMatt McGurn 1819c600e38SMatt McGurn for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 1829c600e38SMatt McGurn if (globalvcdof[c]) { 1839c600e38SMatt McGurn const DMPolytopeType ict = (DMPolytopeType)c; 1849c600e38SMatt McGurn 1859c600e38SMatt McGurn PetscCall(DMLabelGetStratumBounds(ctLabel, ict, &cStart, &cEnd)); 1869c600e38SMatt McGurn sStart[t] = cStart; 1879c600e38SMatt McGurn sEnd[t] = cEnd; 1889c600e38SMatt McGurn ft[t] = (globalvcdof[c] == cdim) ? PETSC_VTK_CELL_VECTOR_FIELD : PETSC_VTK_CELL_FIELD; 1899c600e38SMatt McGurn ++t; 1909c600e38SMatt McGurn } 1919c600e38SMatt McGurn } 1929c600e38SMatt McGurn 1934ad8454bSPierre Jolivet if (!*types) { 1949c600e38SMatt McGurn if (field >= 0) { 1959c600e38SMatt McGurn const char *fieldname; 1969c600e38SMatt McGurn 1979c600e38SMatt McGurn PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 1989c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 1999c600e38SMatt McGurn } else { 2009c600e38SMatt McGurn PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 2019c600e38SMatt McGurn } 2029c600e38SMatt McGurn } 2039c600e38SMatt McGurn 2049c600e38SMatt McGurn *ssStart = sStart; 2059c600e38SMatt McGurn *ssEnd = sEnd; 2069c600e38SMatt McGurn *sft = ft; 2079c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2089c600e38SMatt McGurn } 2099c600e38SMatt McGurn 2109c600e38SMatt McGurn PetscErrorCode DMPlexRestoreFieldTypes_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *types, PetscInt **sStart, PetscInt **sEnd, PetscViewerVTKFieldType **ft) 2119c600e38SMatt McGurn { 2129c600e38SMatt McGurn PetscFunctionBegin; 2139c600e38SMatt McGurn PetscCall(PetscFree3(*sStart, *sEnd, *ft)); 2149c600e38SMatt McGurn PetscFunctionReturn(PETSC_SUCCESS); 2159c600e38SMatt McGurn } 2169c600e38SMatt McGurn 217d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 218d71ae5a4SJacob Faibussowitsch { 219412e9a14SMatthew G. Knepley PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd; 220a99a26bcSAdrian Croucher PetscInt vcdof[2] = {0, 0}, globalvcdof[2]; 2217e42fee7SMatthew G. Knepley 2227e42fee7SMatthew G. Knepley PetscFunctionBegin; 223e630c359SToby Isaac *ft = PETSC_VTK_INVALID; 2249566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 2259566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2269566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 2287e42fee7SMatthew G. Knepley if (field >= 0) { 2299566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0])); 2309566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1])); 2317e42fee7SMatthew G. Knepley } else { 2329566063dSJacob Faibussowitsch if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0])); 2339566063dSJacob Faibussowitsch if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1])); 2347e42fee7SMatthew G. Knepley } 235712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 236a99a26bcSAdrian Croucher if (globalvcdof[0]) { 2377e42fee7SMatthew G. Knepley *sStart = vStart; 2387e42fee7SMatthew G. Knepley *sEnd = vEnd; 239f094498dSMatthew G. Knepley if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 2407e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_POINT_FIELD; 241a99a26bcSAdrian Croucher } else if (globalvcdof[1]) { 2427e42fee7SMatthew G. Knepley *sStart = cStart; 2437e42fee7SMatthew G. Knepley *sEnd = cEnd; 244f094498dSMatthew G. Knepley if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 2457e42fee7SMatthew G. Knepley else *ft = PETSC_VTK_CELL_FIELD; 246e630c359SToby Isaac } else { 247e630c359SToby Isaac if (field >= 0) { 248e630c359SToby Isaac const char *fieldname; 249e630c359SToby Isaac 2509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(section, field, &fieldname)); 25163a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname)); 252e630c359SToby Isaac } else { 25363a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n")); 254e630c359SToby Isaac } 255e630c359SToby Isaac } 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2577e42fee7SMatthew G. Knepley } 2587e42fee7SMatthew G. Knepley 2596913077dSMatthew G. Knepley /*@ 2606913077dSMatthew G. Knepley DMPlexVecView1D - Plot many 1D solutions on the same line graph 2616913077dSMatthew G. Knepley 26220f4b53cSBarry Smith Collective 2636913077dSMatthew G. Knepley 2646913077dSMatthew G. Knepley Input Parameters: 265a1cb98faSBarry Smith + dm - The `DMPLEX` object 2666913077dSMatthew G. Knepley . n - The number of vectors 2676913077dSMatthew G. Knepley . u - The array of local vectors 268a1cb98faSBarry Smith - viewer - The `PetscViewer` 2696913077dSMatthew G. Knepley 2706913077dSMatthew G. Knepley Level: advanced 2716913077dSMatthew G. Knepley 2721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()` 2736913077dSMatthew G. Knepley @*/ 274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) 275d71ae5a4SJacob Faibussowitsch { 2766913077dSMatthew G. Knepley PetscDS ds; 2776913077dSMatthew G. Knepley PetscDraw draw = NULL; 2786913077dSMatthew G. Knepley PetscDrawLG lg; 2796913077dSMatthew G. Knepley Vec coordinates; 2806913077dSMatthew G. Knepley const PetscScalar *coords, **sol; 2816913077dSMatthew G. Knepley PetscReal *vals; 2826913077dSMatthew G. Knepley PetscInt *Nc; 2836913077dSMatthew G. Knepley PetscInt Nf, f, c, Nl, l, i, vStart, vEnd, v; 2846913077dSMatthew G. Knepley char **names; 2856913077dSMatthew G. Knepley 2866913077dSMatthew G. Knepley PetscFunctionBegin; 2879566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &ds)); 2889566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(ds, &Nf)); 2899566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalComponents(ds, &Nl)); 2909566063dSJacob Faibussowitsch PetscCall(PetscDSGetComponents(ds, &Nc)); 2916913077dSMatthew G. Knepley 2929566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 2933ba16761SJacob Faibussowitsch if (!draw) PetscFunctionReturn(PETSC_SUCCESS); 2949566063dSJacob Faibussowitsch PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg)); 2956913077dSMatthew G. Knepley 2969566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals)); 2976913077dSMatthew G. Knepley for (i = 0, l = 0; i < n; ++i) { 2986913077dSMatthew G. Knepley const char *vname; 2996913077dSMatthew G. Knepley 3009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)u[i], &vname)); 3016913077dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 3026913077dSMatthew G. Knepley PetscObject disc; 3036913077dSMatthew G. Knepley const char *fname; 3046913077dSMatthew G. Knepley char tmpname[PETSC_MAX_PATH_LEN]; 3056913077dSMatthew G. Knepley 3069566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(ds, f, &disc)); 3076913077dSMatthew G. Knepley /* TODO Create names for components */ 3086913077dSMatthew G. Knepley for (c = 0; c < Nc[f]; ++c, ++l) { 3099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(disc, &fname)); 310c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname))); 311c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname))); 312c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname))); 3139566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(tmpname, &names[l])); 3146913077dSMatthew G. Knepley } 3156913077dSMatthew G. Knepley } 3166913077dSMatthew G. Knepley } 3179566063dSJacob Faibussowitsch PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names)); 3186913077dSMatthew G. Knepley /* Just add P_1 support for now */ 3199566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &coords)); 3229566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i])); 3236913077dSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 3246913077dSMatthew G. Knepley PetscScalar *x, *svals; 3256913077dSMatthew G. Knepley 3269566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, coords, &x)); 3276913077dSMatthew G. Knepley for (i = 0; i < n; ++i) { 3289566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals)); 3296913077dSMatthew G. Knepley for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]); 3306913077dSMatthew G. Knepley } 3319566063dSJacob Faibussowitsch PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals)); 3326913077dSMatthew G. Knepley } 3339566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &coords)); 3349566063dSJacob Faibussowitsch for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i])); 3359566063dSJacob Faibussowitsch for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l])); 3369566063dSJacob Faibussowitsch PetscCall(PetscFree3(sol, names, vals)); 3376913077dSMatthew G. Knepley 3389566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDraw(lg)); 3399566063dSJacob Faibussowitsch PetscCall(PetscDrawLGDestroy(&lg)); 3403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3416913077dSMatthew G. Knepley } 3426913077dSMatthew G. Knepley 343d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) 344d71ae5a4SJacob Faibussowitsch { 3456913077dSMatthew G. Knepley DM dm; 3466913077dSMatthew G. Knepley 3476913077dSMatthew G. Knepley PetscFunctionBegin; 3489566063dSJacob Faibussowitsch PetscCall(VecGetDM(u, &dm)); 3499566063dSJacob Faibussowitsch PetscCall(DMPlexVecView1D(dm, 1, &u, viewer)); 3503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3516913077dSMatthew G. Knepley } 3526913077dSMatthew G. Knepley 353d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) 354d71ae5a4SJacob Faibussowitsch { 355e412dcbdSMatthew G. Knepley DM dm; 356d1df6f1dSMatthew G. Knepley PetscSection s; 357e412dcbdSMatthew G. Knepley PetscDraw draw, popup; 358e412dcbdSMatthew G. Knepley DM cdm; 359e412dcbdSMatthew G. Knepley PetscSection coordSection; 360e412dcbdSMatthew G. Knepley Vec coordinates; 361c9c77995SMatthew G. Knepley const PetscScalar *array; 362c9c77995SMatthew G. Knepley PetscReal lbound[3], ubound[3]; 363339e3443SMatthew G. Knepley PetscReal vbound[2], time; 3646913077dSMatthew G. Knepley PetscBool flg; 365d1df6f1dSMatthew G. Knepley PetscInt dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0; 366e412dcbdSMatthew G. Knepley const char *name; 367339e3443SMatthew G. Knepley char title[PETSC_MAX_PATH_LEN]; 368e412dcbdSMatthew G. Knepley 369e412dcbdSMatthew G. Knepley PetscFunctionBegin; 3709566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 3719566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 3729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 3739566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 3749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 3759566063dSJacob Faibussowitsch PetscCall(DMGetCoarsenLevel(dm, &level)); 3769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 3779566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 3789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 3799566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 3809566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 381e412dcbdSMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 3839566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, &time)); 384e412dcbdSMatthew G. Knepley 3859566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coordinates, &N)); 386c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, lbound, ubound)); 3879566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 388e412dcbdSMatthew G. Knepley 389d1df6f1dSMatthew G. Knepley /* Could implement something like DMDASelectFields() */ 390d1df6f1dSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 391d1df6f1dSMatthew G. Knepley DM fdm = dm; 392d1df6f1dSMatthew G. Knepley Vec fv = v; 393d1df6f1dSMatthew G. Knepley IS fis; 394d1df6f1dSMatthew G. Knepley char prefix[PETSC_MAX_PATH_LEN]; 395d1df6f1dSMatthew G. Knepley const char *fname; 396d1df6f1dSMatthew G. Knepley 3979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(s, f, &Nc)); 3989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldName(s, f, &fname)); 399d1df6f1dSMatthew G. Knepley 4009566063dSJacob Faibussowitsch if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix))); 401ad540459SPierre Jolivet else prefix[0] = '\0'; 402d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4039566063dSJacob Faibussowitsch PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm)); 4049566063dSJacob Faibussowitsch PetscCall(VecGetSubVector(v, fis, &fv)); 4059566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix))); 4069566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix))); 407d1df6f1dSMatthew G. Knepley } 408d1df6f1dSMatthew G. Knepley for (comp = 0; comp < Nc; ++comp, ++w) { 409d1df6f1dSMatthew G. Knepley PetscInt nmax = 2; 410d1df6f1dSMatthew G. Knepley 4119566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw)); 41263a3b9bcSJacob Faibussowitsch if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time)); 41363a3b9bcSJacob Faibussowitsch else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time)); 4149566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, title)); 415d1df6f1dSMatthew G. Knepley 416d1df6f1dSMatthew G. Knepley /* TODO Get max and min only for this component */ 4179566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg)); 418339e3443SMatthew G. Knepley if (!flg) { 4199566063dSJacob Faibussowitsch PetscCall(VecMin(fv, NULL, &vbound[0])); 4209566063dSJacob Faibussowitsch PetscCall(VecMax(fv, NULL, &vbound[1])); 421d1df6f1dSMatthew G. Knepley if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0; 422339e3443SMatthew G. Knepley } 423c9c77995SMatthew G. Knepley 4249566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPopup(draw, &popup)); 4259566063dSJacob Faibussowitsch PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1])); 426c9c77995SMatthew G. Knepley PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1])); 4279566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(fv, &array)); 428e412dcbdSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 429b7550097SMatthew G. Knepley DMPolytopeType ct; 43099a2f7bcSMatthew G. Knepley PetscScalar *coords = NULL, *a = NULL; 431c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 432c9c77995SMatthew G. Knepley PetscBool isDG; 433*6497c311SBarry Smith PetscInt numCoords; 434*6497c311SBarry Smith int color[4] = {-1, -1, -1, -1}; 435e412dcbdSMatthew G. Knepley 436b7550097SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, c, &ct)); 4379566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(fdm, c, array, &a)); 438339e3443SMatthew G. Knepley if (a) { 439d1df6f1dSMatthew G. Knepley color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]); 440339e3443SMatthew G. Knepley color[1] = color[2] = color[3] = color[0]; 441339e3443SMatthew G. Knepley } else { 442339e3443SMatthew G. Knepley PetscScalar *vals = NULL; 443339e3443SMatthew G. Knepley PetscInt numVals, va; 444339e3443SMatthew G. Knepley 4459566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals)); 446b7550097SMatthew G. Knepley if (!numVals) { 447b7550097SMatthew G. Knepley PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 448b7550097SMatthew G. Knepley continue; 449b7550097SMatthew G. Knepley } 45063a3b9bcSJacob 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); 451d1df6f1dSMatthew G. Knepley switch (numVals / Nc) { 452b7550097SMatthew G. Knepley case 1: /* P1 Clamped Segment Prism */ 453b7550097SMatthew G. Knepley case 2: /* P1 Segment Prism, P2 Clamped Segment Prism */ 454b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a tensor segment, but it is a %s", DMPolytopeTypes[ct]); 455b7550097SMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 456b7550097SMatthew G. Knepley break; 457d1df6f1dSMatthew G. Knepley case 3: /* P1 Triangle */ 458d1df6f1dSMatthew G. Knepley case 4: /* P1 Quadrangle */ 459b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_TRIANGLE || ct == DM_POLYTOPE_QUADRILATERAL || ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a triangle or quad, but it is a %s", DMPolytopeTypes[ct]); 460d1df6f1dSMatthew G. Knepley for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]); 461339e3443SMatthew G. Knepley break; 462d1df6f1dSMatthew G. Knepley case 6: /* P2 Triangle */ 463d1df6f1dSMatthew G. Knepley case 8: /* P2 Quadrangle */ 464b7550097SMatthew G. Knepley PetscCheck(ct == DM_POLYTOPE_TRIANGLE || ct == DM_POLYTOPE_QUADRILATERAL || ct == DM_POLYTOPE_SEG_PRISM_TENSOR, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell should be a triangle or quad, but it is a %s", DMPolytopeTypes[ct]); 465d1df6f1dSMatthew 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]); 466d1df6f1dSMatthew G. Knepley break; 467d71ae5a4SJacob Faibussowitsch default: 468d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc); 469339e3443SMatthew G. Knepley } 4709566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals)); 471339e3443SMatthew G. Knepley } 472c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 473e412dcbdSMatthew G. Knepley switch (numCoords) { 474e412dcbdSMatthew G. Knepley case 6: 4759edc3542SMatthew Knepley case 12: /* Localized triangle */ 4769566063dSJacob 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])); 477e412dcbdSMatthew G. Knepley break; 478e412dcbdSMatthew G. Knepley case 8: 4799edc3542SMatthew Knepley case 16: /* Localized quadrilateral */ 480b7550097SMatthew G. Knepley if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR) { 481b7550097SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscMax(color[0], color[1]))); 482b7550097SMatthew G. Knepley } else { 4839566063dSJacob 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])); 4849566063dSJacob 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])); 485b7550097SMatthew G. Knepley } 486e412dcbdSMatthew G. Knepley break; 487d71ae5a4SJacob Faibussowitsch default: 488d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords); 489e412dcbdSMatthew G. Knepley } 490c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 491e412dcbdSMatthew G. Knepley } 4929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(fv, &array)); 4939566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 4949566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 4959566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 496d1df6f1dSMatthew G. Knepley } 497d1df6f1dSMatthew G. Knepley if (Nf > 1) { 4989566063dSJacob Faibussowitsch PetscCall(VecRestoreSubVector(v, fis, &fv)); 4999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fis)); 5009566063dSJacob Faibussowitsch PetscCall(DMDestroy(&fdm)); 501d1df6f1dSMatthew G. Knepley } 502d1df6f1dSMatthew G. Knepley } 5033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 504e412dcbdSMatthew G. Knepley } 505e412dcbdSMatthew G. Knepley 506d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) 507d71ae5a4SJacob Faibussowitsch { 5086913077dSMatthew G. Knepley DM dm; 5096913077dSMatthew G. Knepley PetscDraw draw; 5106913077dSMatthew G. Knepley PetscInt dim; 5116913077dSMatthew G. Knepley PetscBool isnull; 5126913077dSMatthew G. Knepley 5136913077dSMatthew G. Knepley PetscFunctionBegin; 5149566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 5159566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 5163ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 5176913077dSMatthew G. Knepley 5189566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5206913077dSMatthew G. Knepley switch (dim) { 521d71ae5a4SJacob Faibussowitsch case 1: 522d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); 523d71ae5a4SJacob Faibussowitsch break; 524d71ae5a4SJacob Faibussowitsch case 2: 525d71ae5a4SJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); 526d71ae5a4SJacob Faibussowitsch break; 527d71ae5a4SJacob Faibussowitsch default: 528d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim); 5296913077dSMatthew G. Knepley } 5303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5316913077dSMatthew G. Knepley } 5326913077dSMatthew G. Knepley 533d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) 534d71ae5a4SJacob Faibussowitsch { 535684b87d9SLisandro Dalcin DM dm; 536684b87d9SLisandro Dalcin Vec locv; 537684b87d9SLisandro Dalcin const char *name; 538684b87d9SLisandro Dalcin PetscSection section; 539684b87d9SLisandro Dalcin PetscInt pStart, pEnd; 540e630c359SToby Isaac PetscInt numFields; 541684b87d9SLisandro Dalcin PetscViewerVTKFieldType ft; 542684b87d9SLisandro Dalcin 543684b87d9SLisandro Dalcin PetscFunctionBegin; 5449566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 5459566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */ 5469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 5479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 5489566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 5499566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 5509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 551e630c359SToby Isaac if (!numFields) { 5529566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft)); 5539566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv)); 554e630c359SToby Isaac } else { 555e630c359SToby Isaac PetscInt f; 556e630c359SToby Isaac 557e630c359SToby Isaac for (f = 0; f < numFields; f++) { 5589566063dSJacob Faibussowitsch PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft)); 559e630c359SToby Isaac if (ft == PETSC_VTK_INVALID) continue; 5609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)locv)); 5619566063dSJacob Faibussowitsch PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv)); 562e630c359SToby Isaac } 5639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&locv)); 564e630c359SToby Isaac } 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566684b87d9SLisandro Dalcin } 567684b87d9SLisandro Dalcin 568d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 569d71ae5a4SJacob Faibussowitsch { 570552f7358SJed Brown DM dm; 5715f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns; 572552f7358SJed Brown 573552f7358SJed Brown PetscFunctionBegin; 5749566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 57528b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 5769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 5779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 5789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 5799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 5805f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 5815f34f2dcSJed Brown if (isvtk || ishdf5 || isdraw || isglvis || iscgns) { 582684b87d9SLisandro Dalcin PetscInt i, numFields; 583684b87d9SLisandro Dalcin PetscObject fe; 584ef31f671SMatthew G. Knepley PetscBool fem = PETSC_FALSE; 585684b87d9SLisandro Dalcin Vec locv = v; 586684b87d9SLisandro Dalcin const char *name; 587684b87d9SLisandro Dalcin PetscInt step; 588684b87d9SLisandro Dalcin PetscReal time; 589ef31f671SMatthew G. Knepley 5909566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &numFields)); 591684b87d9SLisandro Dalcin for (i = 0; i < numFields; i++) { 5929566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, i, NULL, &fe)); 5939371c9d4SSatish Balay if (fe->classid == PETSCFE_CLASSID) { 5949371c9d4SSatish Balay fem = PETSC_TRUE; 5959371c9d4SSatish Balay break; 5969371c9d4SSatish Balay } 597ef31f671SMatthew G. Knepley } 598684b87d9SLisandro Dalcin if (fem) { 599798534f6SMatthew G. Knepley PetscObject isZero; 600798534f6SMatthew G. Knepley 6019566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6029566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6049566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6059566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6069566063dSJacob Faibussowitsch PetscCall(VecCopy(v, locv)); 6079566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time)); 6089566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL)); 609ef31f671SMatthew G. Knepley } 610552f7358SJed Brown if (isvtk) { 6119566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_VTK(locv, viewer)); 612b136c2c9SMatthew G. Knepley } else if (ishdf5) { 613b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6149566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer)); 615b136c2c9SMatthew G. Knepley #else 616b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 617b136c2c9SMatthew G. Knepley #endif 618f13a32a3SMatthew G. Knepley } else if (isdraw) { 6199566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local_Draw(locv, viewer)); 620684b87d9SLisandro Dalcin } else if (isglvis) { 6219566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL)); 6229566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisSetSnapId(viewer, step)); 6239566063dSJacob Faibussowitsch PetscCall(VecView_GLVis(locv, viewer)); 6245f34f2dcSJed Brown } else if (iscgns) { 6255f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 6265f34f2dcSJed Brown PetscCall(VecView_Plex_Local_CGNS(locv, viewer)); 6275f34f2dcSJed Brown #else 6285f34f2dcSJed Brown SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns"); 6295f34f2dcSJed Brown #endif 630684b87d9SLisandro Dalcin } 631798534f6SMatthew G. Knepley if (fem) { 6329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6339566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 634798534f6SMatthew G. Knepley } 635552f7358SJed Brown } else { 636684b87d9SLisandro Dalcin PetscBool isseq; 637684b87d9SLisandro Dalcin 6389566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6399566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6409566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 641552f7358SJed Brown } 6423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 643552f7358SJed Brown } 644552f7358SJed Brown 645d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 646d71ae5a4SJacob Faibussowitsch { 647552f7358SJed Brown DM dm; 6485f34f2dcSJed Brown PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns; 649552f7358SJed Brown 650552f7358SJed Brown PetscFunctionBegin; 6519566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 65228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 6539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 6549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 6559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 6569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 6575f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 6595f34f2dcSJed Brown if (isvtk || isdraw || isglvis || iscgns) { 660552f7358SJed Brown Vec locv; 661798534f6SMatthew G. Knepley PetscObject isZero; 662552f7358SJed Brown const char *name; 663552f7358SJed Brown 6649566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(dm, &locv)); 6659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 6669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)locv, name)); 6679566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv)); 6689566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv)); 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero)); 6709566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero)); 6719566063dSJacob Faibussowitsch PetscCall(VecView_Plex_Local(locv, viewer)); 6729566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL)); 6739566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(dm, &locv)); 6744d7cf8c0SStefano Zampini /* Call flush for proper logging of VecView timings */ 6754d7cf8c0SStefano Zampini if (isvtk) PetscCall(PetscViewerFlush(viewer)); 676b136c2c9SMatthew G. Knepley } else if (ishdf5) { 677b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 6789566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Internal(v, viewer)); 679b136c2c9SMatthew G. Knepley #else 680b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 681b136c2c9SMatthew G. Knepley #endif 6826823f3c5SBlaise Bourdin } else if (isexodusii) { 6836823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 6849566063dSJacob Faibussowitsch PetscCall(VecView_PlexExodusII_Internal(v, viewer)); 6856823f3c5SBlaise Bourdin #else 6866823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 6876823f3c5SBlaise Bourdin #endif 688552f7358SJed Brown } else { 689684b87d9SLisandro Dalcin PetscBool isseq; 690684b87d9SLisandro Dalcin 6919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 6929566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 6939566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 694552f7358SJed Brown } 6953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 696552f7358SJed Brown } 697552f7358SJed Brown 698d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 699d71ae5a4SJacob Faibussowitsch { 700d930f514SMatthew G. Knepley DM dm; 701d930f514SMatthew G. Knepley MPI_Comm comm; 702d930f514SMatthew G. Knepley PetscViewerFormat format; 703d930f514SMatthew G. Knepley Vec v; 704d930f514SMatthew G. Knepley PetscBool isvtk, ishdf5; 705d930f514SMatthew G. Knepley 706d930f514SMatthew G. Knepley PetscFunctionBegin; 7079566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 7089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm)); 70928b400f6SJacob Faibussowitsch PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7109566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 7119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 713d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 714a8ad634aSStefano Zampini /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */ 715a8ad634aSStefano Zampini /* this need a better fix */ 716a8ad634aSStefano Zampini if (dm->useNatural) { 717a8ad634aSStefano Zampini if (dm->sfNatural) { 718d930f514SMatthew G. Knepley const char *vecname; 719d930f514SMatthew G. Knepley PetscInt n, nroots; 720d930f514SMatthew G. Knepley 7219566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(originalv, &n)); 7229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL)); 723d930f514SMatthew G. Knepley if (n == nroots) { 724f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 7259566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v)); 7269566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v)); 7279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 7289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 729d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 730d930f514SMatthew G. Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 731a8ad634aSStefano Zampini } else v = originalv; 732a8ad634aSStefano Zampini } else v = originalv; 733a8ad634aSStefano Zampini 734d930f514SMatthew G. Knepley if (ishdf5) { 735d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7369566063dSJacob Faibussowitsch PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer)); 737d930f514SMatthew G. Knepley #else 738d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 739d930f514SMatthew G. Knepley #endif 740d930f514SMatthew G. Knepley } else if (isvtk) { 741d930f514SMatthew G. Knepley SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 742d930f514SMatthew G. Knepley } else { 743d930f514SMatthew G. Knepley PetscBool isseq; 744d930f514SMatthew G. Knepley 7459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 7469566063dSJacob Faibussowitsch if (isseq) PetscCall(VecView_Seq(v, viewer)); 7479566063dSJacob Faibussowitsch else PetscCall(VecView_MPI(v, viewer)); 748d930f514SMatthew G. Knepley } 749f16a8b29SMatthew G. Knepley if (v != originalv) PetscCall(VecDestroy(&v)); 7503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 751d930f514SMatthew G. Knepley } 752d930f514SMatthew G. Knepley 753d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 754d71ae5a4SJacob Faibussowitsch { 7552c40f234SMatthew G. Knepley DM dm; 7562c40f234SMatthew G. Knepley PetscBool ishdf5; 7572c40f234SMatthew G. Knepley 7582c40f234SMatthew G. Knepley PetscFunctionBegin; 7599566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 76028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7622c40f234SMatthew G. Knepley if (ishdf5) { 7632c40f234SMatthew G. Knepley DM dmBC; 7642c40f234SMatthew G. Knepley Vec gv; 7652c40f234SMatthew G. Knepley const char *name; 7662c40f234SMatthew G. Knepley 7679566063dSJacob Faibussowitsch PetscCall(DMGetOutputDM(dm, &dmBC)); 7689566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dmBC, &gv)); 7699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)v, &name)); 7709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)gv, name)); 7719566063dSJacob Faibussowitsch PetscCall(VecLoad_Default(gv, viewer)); 7729566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v)); 7739566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v)); 7749566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dmBC, &gv)); 7751baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 7763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7772c40f234SMatthew G. Knepley } 7782c40f234SMatthew G. Knepley 779d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 780d71ae5a4SJacob Faibussowitsch { 7812c40f234SMatthew G. Knepley DM dm; 7826823f3c5SBlaise Bourdin PetscBool ishdf5, isexodusii; 7832c40f234SMatthew G. Knepley 7842c40f234SMatthew G. Knepley PetscFunctionBegin; 7859566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 78628b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 7879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 7889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii)); 7892c40f234SMatthew G. Knepley if (ishdf5) { 790878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 7919566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer)); 792b136c2c9SMatthew G. Knepley #else 793b136c2c9SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 794878b459fSMatthew G. Knepley #endif 7956823f3c5SBlaise Bourdin } else if (isexodusii) { 7966823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII) 7979566063dSJacob Faibussowitsch PetscCall(VecLoad_PlexExodusII_Internal(v, viewer)); 7986823f3c5SBlaise Bourdin #else 7996823f3c5SBlaise Bourdin SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii"); 8006823f3c5SBlaise Bourdin #endif 8011baa6e33SBarry Smith } else PetscCall(VecLoad_Default(v, viewer)); 8023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 803552f7358SJed Brown } 804552f7358SJed Brown 805d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 806d71ae5a4SJacob Faibussowitsch { 807d930f514SMatthew G. Knepley DM dm; 808d930f514SMatthew G. Knepley PetscViewerFormat format; 809d930f514SMatthew G. Knepley PetscBool ishdf5; 810d930f514SMatthew G. Knepley 811d930f514SMatthew G. Knepley PetscFunctionBegin; 8129566063dSJacob Faibussowitsch PetscCall(VecGetDM(originalv, &dm)); 81328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 8149566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 8159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 816d930f514SMatthew G. Knepley if (format == PETSC_VIEWER_NATIVE) { 817a8ad634aSStefano Zampini if (dm->useNatural) { 818d930f514SMatthew G. Knepley if (dm->sfNatural) { 819d930f514SMatthew G. Knepley if (ishdf5) { 820d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 821d930f514SMatthew G. Knepley Vec v; 822d930f514SMatthew G. Knepley const char *vecname; 823d930f514SMatthew G. Knepley 824f16a8b29SMatthew G. Knepley PetscCall(DMPlexCreateNaturalVector(dm, &v)); 8259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname)); 8269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)v, vecname)); 8279566063dSJacob Faibussowitsch PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer)); 8289566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv)); 8299566063dSJacob Faibussowitsch PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv)); 830f16a8b29SMatthew G. Knepley PetscCall(VecDestroy(&v)); 831d930f514SMatthew G. Knepley #else 832d930f514SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 833d930f514SMatthew G. Knepley #endif 834d930f514SMatthew G. Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 835d930f514SMatthew G. Knepley } 8361baa6e33SBarry Smith } else PetscCall(VecLoad_Default(originalv, viewer)); 837d930f514SMatthew G. Knepley } 8383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 839d930f514SMatthew G. Knepley } 840d930f514SMatthew G. Knepley 841d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 842d71ae5a4SJacob Faibussowitsch { 843731e8ddeSMatthew G. Knepley PetscSection coordSection; 844731e8ddeSMatthew G. Knepley Vec coordinates; 845ba2698f1SMatthew G. Knepley DMLabel depthLabel, celltypeLabel; 846731e8ddeSMatthew G. Knepley const char *name[4]; 847731e8ddeSMatthew G. Knepley const PetscScalar *a; 848731e8ddeSMatthew G. Knepley PetscInt dim, pStart, pEnd, cStart, cEnd, c; 849731e8ddeSMatthew G. Knepley 850731e8ddeSMatthew G. Knepley PetscFunctionBegin; 8519566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 8529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 8539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 8559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel)); 8569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd)); 8589566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &a)); 859731e8ddeSMatthew G. Knepley name[0] = "vertex"; 860731e8ddeSMatthew G. Knepley name[1] = "edge"; 861731e8ddeSMatthew G. Knepley name[dim - 1] = "face"; 862731e8ddeSMatthew G. Knepley name[dim] = "cell"; 863731e8ddeSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 864731e8ddeSMatthew G. Knepley PetscInt *closure = NULL; 865ba2698f1SMatthew G. Knepley PetscInt closureSize, cl, ct; 866731e8ddeSMatthew G. Knepley 8679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(celltypeLabel, c, &ct)); 86863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct])); 8699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 871731e8ddeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 872731e8ddeSMatthew G. Knepley PetscInt point = closure[cl], depth, dof, off, d, p; 873731e8ddeSMatthew G. Knepley 874731e8ddeSMatthew G. Knepley if ((point < pStart) || (point >= pEnd)) continue; 8759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, point, &dof)); 876731e8ddeSMatthew G. Knepley if (!dof) continue; 8779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, point, &depth)); 8789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, point, &off)); 87963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point)); 880731e8ddeSMatthew G. Knepley for (p = 0; p < dof / dim; ++p) { 8819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 882731e8ddeSMatthew G. Knepley for (d = 0; d < dim; ++d) { 8839566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 8849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d]))); 885731e8ddeSMatthew G. Knepley } 8869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 887731e8ddeSMatthew G. Knepley } 8889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 889731e8ddeSMatthew G. Knepley } 8909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 8919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 892731e8ddeSMatthew G. Knepley } 8939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &a)); 8943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 895731e8ddeSMatthew G. Knepley } 896731e8ddeSMatthew G. Knepley 8979371c9d4SSatish Balay typedef enum { 8989371c9d4SSatish Balay CS_CARTESIAN, 8999371c9d4SSatish Balay CS_POLAR, 9009371c9d4SSatish Balay CS_CYLINDRICAL, 9019371c9d4SSatish Balay CS_SPHERICAL 9029371c9d4SSatish Balay } CoordSystem; 90319ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL}; 90419ad8254SMatthew G. Knepley 905d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) 906d71ae5a4SJacob Faibussowitsch { 90719ad8254SMatthew G. Knepley PetscInt i; 90819ad8254SMatthew G. Knepley 90919ad8254SMatthew G. Knepley PetscFunctionBegin; 91019ad8254SMatthew G. Knepley if (dim > 3) { 9119566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i]))); 91219ad8254SMatthew G. Knepley } else { 913bd83fdcbSStefano Zampini PetscReal coords[3], trcoords[3] = {0., 0., 0.}; 91419ad8254SMatthew G. Knepley 91519ad8254SMatthew G. Knepley for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]); 91619ad8254SMatthew G. Knepley switch (cs) { 9179371c9d4SSatish Balay case CS_CARTESIAN: 9189371c9d4SSatish Balay for (i = 0; i < dim; ++i) trcoords[i] = coords[i]; 9199371c9d4SSatish Balay break; 92019ad8254SMatthew G. Knepley case CS_POLAR: 92163a3b9bcSJacob Faibussowitsch PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim); 92219ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 92319ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 92419ad8254SMatthew G. Knepley break; 92519ad8254SMatthew G. Knepley case CS_CYLINDRICAL: 92663a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 92719ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])); 92819ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(coords[1], coords[0]); 92919ad8254SMatthew G. Knepley trcoords[2] = coords[2]; 93019ad8254SMatthew G. Knepley break; 93119ad8254SMatthew G. Knepley case CS_SPHERICAL: 93263a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim); 93319ad8254SMatthew G. Knepley trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2])); 93419ad8254SMatthew G. Knepley trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]); 93519ad8254SMatthew G. Knepley trcoords[2] = PetscAtan2Real(coords[1], coords[0]); 93619ad8254SMatthew G. Knepley break; 93719ad8254SMatthew G. Knepley } 9389566063dSJacob Faibussowitsch for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i])); 93919ad8254SMatthew G. Knepley } 9403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 94119ad8254SMatthew G. Knepley } 94219ad8254SMatthew G. Knepley 943d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 944d71ae5a4SJacob Faibussowitsch { 945552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 9466858538eSMatthew G. Knepley DM cdm, cdmCell; 9476858538eSMatthew G. Knepley PetscSection coordSection, coordSectionCell; 9486858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 949552f7358SJed Brown PetscViewerFormat format; 950552f7358SJed Brown 951552f7358SJed Brown PetscFunctionBegin; 9529566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 953552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 954552f7358SJed Brown const char *name; 955f73eea6eSMatthew G. Knepley PetscInt dim, cellHeight, maxConeSize, maxSupportSize; 9569318fe57SMatthew G. Knepley PetscInt pStart, pEnd, p, numLabels, l; 957552f7358SJed Brown PetscMPIInt rank, size; 958552f7358SJed Brown 9599f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 9609f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 9619f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9629f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 9639f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 9649f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 9659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 9669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 9679566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 9689566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9699566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 9709566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9719566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 97263a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 97363a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 97463a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 97563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n")); 9769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 97763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize)); 978552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 979552f7358SJed Brown PetscInt dof, off, s; 980552f7358SJed Brown 9819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 9829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 98348a46eb9SPierre Jolivet for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s])); 984552f7358SJed Brown } 9859566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 98663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n")); 98763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize)); 988552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 989552f7358SJed Brown PetscInt dof, off, c; 990552f7358SJed Brown 9919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 9929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 99348a46eb9SPierre 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])); 994552f7358SJed Brown } 9959566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 9969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 9973d2e540fSStefano Zampini if (coordSection && coordinates) { 99819ad8254SMatthew G. Knepley CoordSystem cs = CS_CARTESIAN; 9996858538eSMatthew G. Knepley const PetscScalar *array, *arrayCell = NULL; 10006858538eSMatthew G. Knepley PetscInt Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p; 100119ad8254SMatthew G. Knepley PetscMPIInt rank; 100219ad8254SMatthew G. Knepley const char *name; 100319ad8254SMatthew G. Knepley 10049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL)); 10059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 10069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(coordSection, &Nf)); 100763a3b9bcSJacob Faibussowitsch PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf); 10089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc)); 10096858538eSMatthew G. Knepley PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd)); 10106858538eSMatthew G. Knepley if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd)); 10116858538eSMatthew G. Knepley pStart = PetscMin(pvStart, pcStart); 10126858538eSMatthew G. Knepley pEnd = PetscMax(pvEnd, pcEnd); 10139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 101463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf)); 101563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " field 0 with %" PetscInt_FMT " components\n", Nc)); 10169566063dSJacob Faibussowitsch if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, " output coordinate system: %s\n", CoordSystems[cs])); 101719ad8254SMatthew G. Knepley 10189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coordinates, &array)); 10196858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell)); 10209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 10219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank)); 102219ad8254SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 102319ad8254SMatthew G. Knepley PetscInt dof, off; 102419ad8254SMatthew G. Knepley 10256858538eSMatthew G. Knepley if (p >= pvStart && p < pvEnd) { 10269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 10279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, p, &off)); 10286858538eSMatthew G. Knepley if (dof) { 1029f2719977SBarry Smith PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dof %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10309566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off])); 10319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 103219ad8254SMatthew G. Knepley } 10336858538eSMatthew G. Knepley } 10346858538eSMatthew G. Knepley if (cdmCell && p >= pcStart && p < pcEnd) { 10356858538eSMatthew G. Knepley PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof)); 10366858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off)); 10376858538eSMatthew G. Knepley if (dof) { 1038f2719977SBarry Smith PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%4" PetscInt_FMT ") dof %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off)); 10396858538eSMatthew G. Knepley PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off])); 10406858538eSMatthew G. Knepley PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 10416858538eSMatthew G. Knepley } 10426858538eSMatthew G. Knepley } 10436858538eSMatthew G. Knepley } 10449566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 10459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 10469566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coordinates, &array)); 10476858538eSMatthew G. Knepley if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell)); 10483d2e540fSStefano Zampini } 10499566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10509566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 10519318fe57SMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 10529318fe57SMatthew G. Knepley DMLabel label; 10539318fe57SMatthew G. Knepley PetscBool isdepth; 10549318fe57SMatthew G. Knepley const char *name; 10559318fe57SMatthew G. Knepley 10569566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 10579566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(name, "depth", &isdepth)); 10589318fe57SMatthew G. Knepley if (isdepth) continue; 10599566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10609566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 10619318fe57SMatthew G. Knepley } 1062552f7358SJed Brown if (size > 1) { 1063552f7358SJed Brown PetscSF sf; 1064552f7358SJed Brown 10659566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 10669566063dSJacob Faibussowitsch PetscCall(PetscSFView(sf, viewer)); 1067552f7358SJed Brown } 10681fca310dSJames Wright if (mesh->periodic.face_sfs) 10691fca310dSJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(PetscSFView(mesh->periodic.face_sfs[i], viewer)); 10709566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1071552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 10720588280cSMatthew G. Knepley const char *name, *color; 10730588280cSMatthew G. Knepley const char *defcolors[3] = {"gray", "orange", "green"}; 10740588280cSMatthew G. Knepley const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 1075fe1cc32dSStefano Zampini char lname[PETSC_MAX_PATH_LEN]; 1076552f7358SJed Brown PetscReal scale = 2.0; 107778081901SStefano Zampini PetscReal tikzscale = 1.0; 1078b7f6ffafSMatthew G. Knepley PetscBool useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE; 10790588280cSMatthew G. Knepley double tcoords[3]; 1080552f7358SJed Brown PetscScalar *coords; 1081b862f699SMatthew G. Knepley PetscInt numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, fStart = 0, fEnd = 0, e, p, n; 1082552f7358SJed Brown PetscMPIInt rank, size; 10830588280cSMatthew G. Knepley char **names, **colors, **lcolors; 1084b7f6ffafSMatthew G. Knepley PetscBool flg, lflg; 1085fe1cc32dSStefano Zampini PetscBT wp = NULL; 1086fe1cc32dSStefano Zampini PetscInt pEnd, pStart; 1087552f7358SJed Brown 10889f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 10899f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 10909f4ada15SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10919f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cdmCell)); 10929f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell)); 10939f4ada15SMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell)); 10949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 10969566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 10970588280cSMatthew G. Knepley numLabels = PetscMax(numLabels, 10); 10980588280cSMatthew G. Knepley numColors = 10; 10990588280cSMatthew G. Knepley numLColors = 10; 11009566063dSJacob Faibussowitsch PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors)); 11019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL)); 11029566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL)); 11039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL)); 1104b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers; 1105b7f6ffafSMatthew G. Knepley for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE; 1106b7f6ffafSMatthew G. Knepley n = 4; 11079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg)); 11081dca8a05SBarry 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); 1109bd3611e6SMatthew G. Knepley n = 4; 11109566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg)); 11111dca8a05SBarry 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); 11129566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels)); 11130588280cSMatthew G. Knepley if (!useLabels) numLabels = 0; 11149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors)); 11150588280cSMatthew G. Knepley if (!useColors) { 11160588280cSMatthew G. Knepley numColors = 3; 11179566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c])); 11180588280cSMatthew G. Knepley } 11199566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors)); 11200588280cSMatthew G. Knepley if (!useColors) { 11210588280cSMatthew G. Knepley numLColors = 4; 11229566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c])); 11230588280cSMatthew G. Knepley } 11249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg)); 1125b7f6ffafSMatthew G. Knepley plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3); 11269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg)); 11271dca8a05SBarry Smith PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated"); 1128202fd40aSStefano Zampini if (depth < dim) plotEdges = PETSC_FALSE; 11299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL)); 1130fe1cc32dSStefano Zampini 1131fe1cc32dSStefano Zampini /* filter points with labelvalue != labeldefaultvalue */ 11329566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 11339566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 11349566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 11359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1136b862f699SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 1137fe1cc32dSStefano Zampini if (lflg) { 1138fe1cc32dSStefano Zampini DMLabel lbl; 1139fe1cc32dSStefano Zampini 11409566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &lbl)); 1141fe1cc32dSStefano Zampini if (lbl) { 1142fe1cc32dSStefano Zampini PetscInt val, defval; 1143fe1cc32dSStefano Zampini 11449566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(lbl, &defval)); 11459566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pEnd - pStart, &wp)); 1146fe1cc32dSStefano Zampini for (c = pStart; c < pEnd; c++) { 1147fe1cc32dSStefano Zampini PetscInt *closure = NULL; 1148fe1cc32dSStefano Zampini PetscInt closureSize; 1149fe1cc32dSStefano Zampini 11509566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(lbl, c, &val)); 1151fe1cc32dSStefano Zampini if (val == defval) continue; 1152fe1cc32dSStefano Zampini 11539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 115448a46eb9SPierre Jolivet for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart)); 11559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1156fe1cc32dSStefano Zampini } 1157fe1cc32dSStefano Zampini } 1158fe1cc32dSStefano Zampini } 1159fe1cc32dSStefano Zampini 11609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 11619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 11629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 11639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\ 11640588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\ 1165552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 1166552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 1167552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 11685f80ce2aSJacob Faibussowitsch \\begin{document}\n")); 11690588280cSMatthew G. Knepley if (size > 1) { 11709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name)); 1171770b213bSMatthew G Knepley for (p = 0; p < size; ++p) { 117263a3b9bcSJacob Faibussowitsch if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", ")); 117363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p)); 1174770b213bSMatthew G Knepley } 11759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n")); 11760588280cSMatthew G. Knepley } 1177b7f6ffafSMatthew G. Knepley if (drawHasse) { 1178b862f699SMatthew G. Knepley PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, PetscMax(fEnd - fStart, cEnd - cStart))); 1179b7f6ffafSMatthew G. Knepley 118063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart)); 118163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1)); 118263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart)); 11839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.)); 118463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart)); 118563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1)); 11869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.)); 118763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart)); 1188b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fStart}{%" PetscInt_FMT "}\n", fStart)); 1189b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fEnd}{%" PetscInt_FMT "}\n", fEnd - 1)); 1190b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\fShift}{%.2f}\n", 3 + (maxStratum - (fEnd - fStart)) / 2.)); 1191b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numFaces}{%" PetscInt_FMT "}\n", fEnd - fStart)); 119263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart)); 119363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1)); 119463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart)); 11959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.)); 1196b7f6ffafSMatthew G. Knepley } 11979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale)); 1198fe1cc32dSStefano Zampini 1199552f7358SJed Brown /* Plot vertices */ 12009566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 1202552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 1203552f7358SJed Brown PetscInt off, dof, d; 12040588280cSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1205552f7358SJed Brown 1206fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, v - pStart)) continue; 12079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 12089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 12099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 121063a3b9bcSJacob Faibussowitsch PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof); 12110588280cSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12120588280cSMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(coords[off + d])); 1213c068d9bbSLisandro Dalcin tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 12140588280cSMatthew G. Knepley } 12150588280cSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12169371c9d4SSatish Balay if (dim == 3) { 12179371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12189371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12199371c9d4SSatish Balay tcoords[2] = -tmp; 12209371c9d4SSatish Balay } 1221552f7358SJed Brown for (d = 0; d < dof; ++d) { 12229566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1224552f7358SJed Brown } 1225b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[0 % numColors]; 1226b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 12270588280cSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 12280588280cSMatthew G. Knepley PetscInt val; 12299566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], v, &val)); 12309371c9d4SSatish Balay if (val >= 0) { 12319371c9d4SSatish Balay color = lcolors[l % numLColors]; 12329371c9d4SSatish Balay isLabeled = PETSC_TRUE; 12339371c9d4SSatish Balay break; 12349371c9d4SSatish Balay } 12350588280cSMatthew G. Knepley } 1236b7f6ffafSMatthew G. Knepley if (drawNumbers[0]) { 123763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v)); 1238b7f6ffafSMatthew G. Knepley } else if (drawColors[0]) { 123963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color)); 12401baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank)); 1241552f7358SJed Brown } 12429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12439566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 1244b7f6ffafSMatthew G. Knepley /* Plot edges */ 1245b7f6ffafSMatthew G. Knepley if (plotEdges) { 12469566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 12479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n")); 1248b7f6ffafSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1249b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1250b7f6ffafSMatthew G. Knepley PetscInt coneSize, offA, offB, dof, d; 1251b7f6ffafSMatthew G. Knepley 1252b7f6ffafSMatthew G. Knepley if (wp && !PetscBTLookup(wp, e - pStart)) continue; 12539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 125463a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize); 12559566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 12569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof)); 12579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA)); 12589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB)); 12599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(")); 1260b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 1261b7f6ffafSMatthew G. Knepley tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d])); 1262b7f6ffafSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1263b7f6ffafSMatthew G. Knepley } 1264b7f6ffafSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 12659371c9d4SSatish Balay if (dim == 3) { 12669371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 12679371c9d4SSatish Balay tcoords[1] = tcoords[2]; 12689371c9d4SSatish Balay tcoords[2] = -tmp; 12699371c9d4SSatish Balay } 1270b7f6ffafSMatthew G. Knepley for (d = 0; d < dof; ++d) { 12719566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 12729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d])); 1273b7f6ffafSMatthew G. Knepley } 1274b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[1 % numColors]; 1275b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1276b7f6ffafSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1277b7f6ffafSMatthew G. Knepley PetscInt val; 1278bd3611e6SMatthew G. Knepley PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 12799371c9d4SSatish Balay if (val >= 0) { 12809371c9d4SSatish Balay color = lcolors[l % numLColors]; 12819371c9d4SSatish Balay break; 12829371c9d4SSatish Balay } 1283b7f6ffafSMatthew G. Knepley } 128463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e)); 1285b7f6ffafSMatthew G. Knepley } 12869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 12879566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 12889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n")); 1289b7f6ffafSMatthew G. Knepley } 1290846a3e8bSMatthew G. Knepley /* Plot cells */ 1291b7f6ffafSMatthew G. Knepley if (dim == 3 || !drawNumbers[1]) { 1292846a3e8bSMatthew G. Knepley for (e = eStart; e < eEnd; ++e) { 1293846a3e8bSMatthew G. Knepley const PetscInt *cone; 1294846a3e8bSMatthew G. Knepley 1295fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, e - pStart)) continue; 1296846a3e8bSMatthew G. Knepley color = colors[rank % numColors]; 1297846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1298846a3e8bSMatthew G. Knepley PetscInt val; 12999566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], e, &val)); 13009371c9d4SSatish Balay if (val >= 0) { 13019371c9d4SSatish Balay color = lcolors[l % numLColors]; 13029371c9d4SSatish Balay break; 13039371c9d4SSatish Balay } 1304846a3e8bSMatthew G. Knepley } 13059566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, e, &cone)); 130663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank)); 1307846a3e8bSMatthew G. Knepley } 1308846a3e8bSMatthew G. Knepley } else { 1309b7f6ffafSMatthew G. Knepley DMPolytopeType ct; 1310846a3e8bSMatthew G. Knepley 1311b7f6ffafSMatthew G. Knepley /* Drawing a 2D polygon */ 1312b7f6ffafSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1313fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 13149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 1315c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct)) { 1316b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1317b7f6ffafSMatthew G. Knepley PetscInt coneSize, e; 1318b7f6ffafSMatthew G. Knepley 13199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 13209566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 1321b7f6ffafSMatthew G. Knepley for (e = 0; e < coneSize; ++e) { 1322b7f6ffafSMatthew G. Knepley const PetscInt *econe; 1323b7f6ffafSMatthew G. Knepley 13249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[e], &econe)); 132563a3b9bcSJacob 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)); 1326b7f6ffafSMatthew G. Knepley } 1327b7f6ffafSMatthew G. Knepley } else { 1328b7f6ffafSMatthew G. Knepley PetscInt *closure = NULL; 1329b7f6ffafSMatthew G. Knepley PetscInt closureSize, Nv = 0, v; 1330b7f6ffafSMatthew G. Knepley 13319566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1332846a3e8bSMatthew G. Knepley for (p = 0; p < closureSize * 2; p += 2) { 1333846a3e8bSMatthew G. Knepley const PetscInt point = closure[p]; 1334846a3e8bSMatthew G. Knepley 1335b7f6ffafSMatthew G. Knepley if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point; 1336846a3e8bSMatthew G. Knepley } 13379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors])); 1338b7f6ffafSMatthew G. Knepley for (v = 0; v <= Nv; ++v) { 1339b7f6ffafSMatthew G. Knepley const PetscInt vertex = closure[v % Nv]; 1340b7f6ffafSMatthew G. Knepley 1341b7f6ffafSMatthew G. Knepley if (v > 0) { 1342b7f6ffafSMatthew G. Knepley if (plotEdges) { 1343b7f6ffafSMatthew G. Knepley const PetscInt *edge; 1344b7f6ffafSMatthew G. Knepley PetscInt endpoints[2], ne; 1345b7f6ffafSMatthew G. Knepley 13469371c9d4SSatish Balay endpoints[0] = closure[v - 1]; 13479371c9d4SSatish Balay endpoints[1] = vertex; 13489566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge)); 134963a3b9bcSJacob Faibussowitsch PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]); 135063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank)); 13519566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge)); 13521baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- ")); 1353b7f6ffafSMatthew G. Knepley } 135463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank)); 1355b7f6ffafSMatthew G. Knepley } 13569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n")); 13579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 1358846a3e8bSMatthew G. Knepley } 1359846a3e8bSMatthew G. Knepley } 1360b7f6ffafSMatthew G. Knepley } 1361846a3e8bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1362846a3e8bSMatthew G. Knepley double ccoords[3] = {0.0, 0.0, 0.0}; 1363846a3e8bSMatthew G. Knepley PetscBool isLabeled = PETSC_FALSE; 1364c713ec31SMatthew G. Knepley PetscScalar *cellCoords = NULL; 1365c713ec31SMatthew G. Knepley const PetscScalar *array; 1366c713ec31SMatthew G. Knepley PetscInt numCoords, cdim, d; 1367c713ec31SMatthew G. Knepley PetscBool isDG; 1368846a3e8bSMatthew G. Knepley 1369fe1cc32dSStefano Zampini if (wp && !PetscBTLookup(wp, c - pStart)) continue; 1370c713ec31SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 1371c713ec31SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1372c713ec31SMatthew G. Knepley PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords); 13739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path (")); 1374c713ec31SMatthew G. Knepley for (p = 0; p < numCoords / cdim; ++p) { 1375c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 1376c713ec31SMatthew G. Knepley tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d])); 1377846a3e8bSMatthew G. Knepley tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 1378846a3e8bSMatthew G. Knepley } 1379846a3e8bSMatthew G. Knepley /* Rotate coordinates since PGF makes z point out of the page instead of up */ 13809371c9d4SSatish Balay if (cdim == 3) { 13819371c9d4SSatish Balay PetscReal tmp = tcoords[1]; 13829371c9d4SSatish Balay tcoords[1] = tcoords[2]; 13839371c9d4SSatish Balay tcoords[2] = -tmp; 13849371c9d4SSatish Balay } 1385ad540459SPierre Jolivet for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d]; 1386846a3e8bSMatthew G. Knepley } 1387ad540459SPierre Jolivet for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim); 1388c713ec31SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords)); 1389c713ec31SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 13909566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ",")); 13919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d])); 1392846a3e8bSMatthew G. Knepley } 1393b7f6ffafSMatthew G. Knepley if (drawHasse) color = colors[depth % numColors]; 1394b7f6ffafSMatthew G. Knepley else color = colors[rank % numColors]; 1395846a3e8bSMatthew G. Knepley for (l = 0; l < numLabels; ++l) { 1396846a3e8bSMatthew G. Knepley PetscInt val; 13979566063dSJacob Faibussowitsch PetscCall(DMGetLabelValue(dm, names[l], c, &val)); 13989371c9d4SSatish Balay if (val >= 0) { 13999371c9d4SSatish Balay color = lcolors[l % numLColors]; 14009371c9d4SSatish Balay isLabeled = PETSC_TRUE; 14019371c9d4SSatish Balay break; 14029371c9d4SSatish Balay } 1403846a3e8bSMatthew G. Knepley } 1404b7f6ffafSMatthew G. Knepley if (drawNumbers[dim]) { 140563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c)); 1406b7f6ffafSMatthew G. Knepley } else if (drawColors[dim]) { 140763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color)); 14081baa6e33SBarry Smith } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank)); 1409846a3e8bSMatthew G. Knepley } 1410b7f6ffafSMatthew G. Knepley if (drawHasse) { 1411b862f699SMatthew G. Knepley int height = 0; 1412b862f699SMatthew G. Knepley 1413b7f6ffafSMatthew G. Knepley color = colors[depth % numColors]; 14149566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n")); 14159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n")); 14169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1417b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,%d) {\\c};\n", rank, color, height++)); 14189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1419552f7358SJed Brown 1420b862f699SMatthew G. Knepley if (depth > 2) { 1421b862f699SMatthew G. Knepley color = colors[1 % numColors]; 1422b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%% Faces\n")); 1423b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\f in {\\fStart,...,\\fEnd}\n")); 1424b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1425b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\f_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\fShift+\\f-\\fStart,%d) {\\f};\n", rank, color, height++)); 1426b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1427b862f699SMatthew G. Knepley } 1428b862f699SMatthew G. Knepley 1429b7f6ffafSMatthew G. Knepley color = colors[1 % numColors]; 14309566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n")); 14319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n")); 14329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1433b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,%d) {\\e};\n", rank, color, height++)); 14349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1435b7f6ffafSMatthew G. Knepley 1436b7f6ffafSMatthew G. Knepley color = colors[0 % numColors]; 14379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n")); 14389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n")); 14399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "{\n")); 1440b862f699SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,%d) {\\v};\n", rank, color, height++)); 14419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "}\n")); 1442b7f6ffafSMatthew G. Knepley 1443b7f6ffafSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1444b7f6ffafSMatthew G. Knepley const PetscInt *cone; 1445b7f6ffafSMatthew G. Knepley PetscInt coneSize, cp; 1446b7f6ffafSMatthew G. Knepley 14479566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 14489566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 144948a46eb9SPierre 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)); 14500588280cSMatthew G. Knepley } 14510588280cSMatthew G. Knepley } 14529566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 14539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 14549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n")); 145563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n")); 14569566063dSJacob Faibussowitsch for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l])); 14579566063dSJacob Faibussowitsch for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c])); 14589566063dSJacob Faibussowitsch for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c])); 14599566063dSJacob Faibussowitsch PetscCall(PetscFree3(names, colors, lcolors)); 14609566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&wp)); 14610f7d6e4aSStefano Zampini } else if (format == PETSC_VIEWER_LOAD_BALANCE) { 14620f7d6e4aSStefano Zampini Vec cown, acown; 14630f7d6e4aSStefano Zampini VecScatter sct; 14640f7d6e4aSStefano Zampini ISLocalToGlobalMapping g2l; 14650f7d6e4aSStefano Zampini IS gid, acis; 14660f7d6e4aSStefano Zampini MPI_Comm comm, ncomm = MPI_COMM_NULL; 14670f7d6e4aSStefano Zampini MPI_Group ggroup, ngroup; 14680f7d6e4aSStefano Zampini PetscScalar *array, nid; 14690f7d6e4aSStefano Zampini const PetscInt *idxs; 14700f7d6e4aSStefano Zampini PetscInt *idxs2, *start, *adjacency, *work; 14710f7d6e4aSStefano Zampini PetscInt64 lm[3], gm[3]; 14720f7d6e4aSStefano Zampini PetscInt i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight; 14730f7d6e4aSStefano Zampini PetscMPIInt d1, d2, rank; 14740f7d6e4aSStefano Zampini 14759566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 14769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1477b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 14789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm)); 14790f7d6e4aSStefano Zampini #endif 14800f7d6e4aSStefano Zampini if (ncomm != MPI_COMM_NULL) { 14819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(comm, &ggroup)); 14829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_group(ncomm, &ngroup)); 14830f7d6e4aSStefano Zampini d1 = 0; 14849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2)); 14850f7d6e4aSStefano Zampini nid = d2; 14869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ggroup)); 14879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Group_free(&ngroup)); 14889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&ncomm)); 14890f7d6e4aSStefano Zampini } else nid = 0.0; 14900f7d6e4aSStefano Zampini 14910f7d6e4aSStefano Zampini /* Get connectivity */ 14929566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 14939566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid)); 14940f7d6e4aSStefano Zampini 14950f7d6e4aSStefano Zampini /* filter overlapped local cells */ 14969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 14979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(gid, &idxs)); 14989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(gid, &cum)); 14999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &idxs2)); 15000f7d6e4aSStefano Zampini for (c = cStart, cum = 0; c < cEnd; c++) { 15010f7d6e4aSStefano Zampini if (idxs[c - cStart] < 0) continue; 15020f7d6e4aSStefano Zampini idxs2[cum++] = idxs[c - cStart]; 15030f7d6e4aSStefano Zampini } 15049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(gid, &idxs)); 150563a3b9bcSJacob Faibussowitsch PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum); 15069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 15079566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid)); 15080f7d6e4aSStefano Zampini 15090f7d6e4aSStefano Zampini /* support for node-aware cell locality */ 15109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis)); 15119566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown)); 15129566063dSJacob Faibussowitsch PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown)); 15139566063dSJacob Faibussowitsch PetscCall(VecGetArray(cown, &array)); 15140f7d6e4aSStefano Zampini for (c = 0; c < numVertices; c++) array[c] = nid; 15159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(cown, &array)); 15169566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct)); 15179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 15189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD)); 15199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&acis)); 15209566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 15219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cown)); 15220f7d6e4aSStefano Zampini 15230f7d6e4aSStefano Zampini /* compute edgeCut */ 15240f7d6e4aSStefano Zampini for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]); 15259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cum, &work)); 15269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l)); 15279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH)); 15289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gid)); 15299566063dSJacob Faibussowitsch PetscCall(VecGetArray(acown, &array)); 15300f7d6e4aSStefano Zampini for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) { 15310f7d6e4aSStefano Zampini PetscInt totl; 15320f7d6e4aSStefano Zampini 15330f7d6e4aSStefano Zampini totl = start[c + 1] - start[c]; 15349566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work)); 15350f7d6e4aSStefano Zampini for (i = 0; i < totl; i++) { 15360f7d6e4aSStefano Zampini if (work[i] < 0) { 15370f7d6e4aSStefano Zampini ect += 1; 15380f7d6e4aSStefano Zampini ectn += (array[i + start[c]] != nid) ? 0 : 1; 15390f7d6e4aSStefano Zampini } 15400f7d6e4aSStefano Zampini } 15410f7d6e4aSStefano Zampini } 15429566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 15439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(acown, &array)); 15440f7d6e4aSStefano Zampini lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT; 15450f7d6e4aSStefano Zampini lm[1] = -numVertices; 15461c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm)); 154763a3b9bcSJacob 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])); 15480f7d6e4aSStefano Zampini lm[0] = ect; /* edgeCut */ 15490f7d6e4aSStefano Zampini lm[1] = ectn; /* node-aware edgeCut */ 15500f7d6e4aSStefano Zampini lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */ 15511c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm)); 155263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2])); 1553b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) 1554f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), gm[0] ? ((double)gm[1]) / ((double)gm[0]) : 1.)); 15550f7d6e4aSStefano Zampini #else 155663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0)); 15570f7d6e4aSStefano Zampini #endif 15589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&g2l)); 15599566063dSJacob Faibussowitsch PetscCall(PetscFree(start)); 15609566063dSJacob Faibussowitsch PetscCall(PetscFree(adjacency)); 15619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&acown)); 1562552f7358SJed Brown } else { 1563412e9a14SMatthew G. Knepley const char *name; 1564d80ece95SMatthew G. Knepley PetscInt *sizes, *hybsizes, *ghostsizes; 1565412e9a14SMatthew G. Knepley PetscInt locDepth, depth, cellHeight, dim, d; 1566d80ece95SMatthew G. Knepley PetscInt pStart, pEnd, p, gcStart, gcEnd, gcNum; 1567ca7bf7eeSMatthew G. Knepley PetscInt numLabels, l, maxSize = 17; 15689318fe57SMatthew G. Knepley DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN; 1569412e9a14SMatthew G. Knepley MPI_Comm comm; 1570412e9a14SMatthew G. Knepley PetscMPIInt size, rank; 1571552f7358SJed Brown 15729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 15739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 15759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15769566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 15779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 157863a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 157963a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 158063a3b9bcSJacob Faibussowitsch if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, " Cells are at height %" PetscInt_FMT "\n", cellHeight)); 15819566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &locDepth)); 15821c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm)); 15832827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd)); 1584d80ece95SMatthew G. Knepley gcNum = gcEnd - gcStart; 15859566063dSJacob Faibussowitsch if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes)); 15869566063dSJacob Faibussowitsch else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes)); 1587412e9a14SMatthew G. Knepley for (d = 0; d <= depth; d++) { 1588412e9a14SMatthew G. Knepley PetscInt Nc[2] = {0, 0}, ict; 1589412e9a14SMatthew G. Knepley 15909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 15919566063dSJacob Faibussowitsch if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0)); 1592412e9a14SMatthew G. Knepley ict = ct0; 15939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm)); 1594412e9a14SMatthew G. Knepley ct0 = (DMPolytopeType)ict; 1595412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1596412e9a14SMatthew G. Knepley DMPolytopeType ct; 1597412e9a14SMatthew G. Knepley 15989566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 1599412e9a14SMatthew G. Knepley if (ct == ct0) ++Nc[0]; 1600412e9a14SMatthew G. Knepley else ++Nc[1]; 1601412e9a14SMatthew G. Knepley } 1602ca7bf7eeSMatthew G. Knepley if (size < maxSize) { 16039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 16049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm)); 16059566063dSJacob Faibussowitsch if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm)); 160663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 1607834065abSMatthew G. Knepley for (p = 0; p < size; ++p) { 1608dd400576SPatrick Sanan if (rank == 0) { 160963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p])); 161063a3b9bcSJacob Faibussowitsch if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p])); 161163a3b9bcSJacob Faibussowitsch if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p])); 1612834065abSMatthew G. Knepley } 1613cbb7f117SMark Adams } 1614ca7bf7eeSMatthew G. Knepley } else { 1615ca7bf7eeSMatthew G. Knepley PetscInt locMinMax[2]; 1616ca7bf7eeSMatthew G. Knepley 16179371c9d4SSatish Balay locMinMax[0] = Nc[0] + Nc[1]; 16189371c9d4SSatish Balay locMinMax[1] = Nc[0] + Nc[1]; 16199566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 16209371c9d4SSatish Balay locMinMax[0] = Nc[1]; 16219371c9d4SSatish Balay locMinMax[1] = Nc[1]; 16229566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes)); 1623ca7bf7eeSMatthew G. Knepley if (d == depth) { 16249371c9d4SSatish Balay locMinMax[0] = gcNum; 16259371c9d4SSatish Balay locMinMax[1] = gcNum; 16269566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes)); 1627ca7bf7eeSMatthew G. Knepley } 162863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d)); 16299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 16309566063dSJacob Faibussowitsch if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1])); 16319566063dSJacob Faibussowitsch if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1])); 1632ca7bf7eeSMatthew G. Knepley } 16339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 1634552f7358SJed Brown } 16359566063dSJacob Faibussowitsch PetscCall(PetscFree3(sizes, hybsizes, ghostsizes)); 16369318fe57SMatthew G. Knepley { 16379318fe57SMatthew G. Knepley const PetscReal *maxCell; 16389318fe57SMatthew G. Knepley const PetscReal *L; 16396858538eSMatthew G. Knepley PetscBool localized; 16409318fe57SMatthew G. Knepley 16414fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L)); 16429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 16436858538eSMatthew G. Knepley if (L || localized) { 16446858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh")); 16459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 16466858538eSMatthew G. Knepley if (L) { 16476858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " (")); 16489318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16496858538eSMatthew G. Knepley if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 16506858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE")); 16519318fe57SMatthew G. Knepley } 16526858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, ")")); 16536858538eSMatthew G. Knepley } 16546858538eSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized")); 16559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 16569318fe57SMatthew G. Knepley } 16579318fe57SMatthew G. Knepley } 16589566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 16599566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n")); 1660a57dd577SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1661a57dd577SMatthew G Knepley DMLabel label; 1662a57dd577SMatthew G Knepley const char *name; 1663281879d4SJames Wright PetscInt *values; 1664a57dd577SMatthew G Knepley PetscInt numValues, v; 1665a57dd577SMatthew G Knepley 16669566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &name)); 16679566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 16689566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 166963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %s: %" PetscInt_FMT " strata with value/size (", name, numValues)); 1670281879d4SJames Wright 1671281879d4SJames Wright { // Extract array of DMLabel values so it can be sorted 1672281879d4SJames Wright IS is_values; 1673281879d4SJames Wright const PetscInt *is_values_local = NULL; 1674281879d4SJames Wright 1675281879d4SJames Wright PetscCall(DMLabelGetValueIS(label, &is_values)); 1676281879d4SJames Wright PetscCall(ISGetIndices(is_values, &is_values_local)); 1677281879d4SJames Wright PetscCall(PetscMalloc1(numValues, &values)); 1678281879d4SJames Wright PetscCall(PetscArraycpy(values, is_values_local, numValues)); 1679281879d4SJames Wright PetscCall(PetscSortInt(numValues, values)); 1680281879d4SJames Wright PetscCall(ISRestoreIndices(is_values, &is_values_local)); 1681281879d4SJames Wright PetscCall(ISDestroy(&is_values)); 1682281879d4SJames Wright } 16839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 1684a57dd577SMatthew G Knepley for (v = 0; v < numValues; ++v) { 1685a57dd577SMatthew G Knepley PetscInt size; 1686a57dd577SMatthew G Knepley 16879566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &size)); 16889566063dSJacob Faibussowitsch if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 168963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size)); 1690a57dd577SMatthew G Knepley } 16919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, ")\n")); 16929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 1693281879d4SJames Wright PetscCall(PetscFree(values)); 1694a57dd577SMatthew G Knepley } 1695c1cad2e7SMatthew G. Knepley { 1696c1cad2e7SMatthew G. Knepley char **labelNames; 1697c1cad2e7SMatthew G. Knepley PetscInt Nl = numLabels; 1698c1cad2e7SMatthew G. Knepley PetscBool flg; 1699c1cad2e7SMatthew G. Knepley 17009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Nl, &labelNames)); 17019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg)); 1702c1cad2e7SMatthew G. Knepley for (l = 0; l < Nl; ++l) { 1703c1cad2e7SMatthew G. Knepley DMLabel label; 1704c1cad2e7SMatthew G. Knepley 17059566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, labelNames[l], &flg)); 1706c1cad2e7SMatthew G. Knepley if (flg) { 17079566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, labelNames[l], &label)); 17089566063dSJacob Faibussowitsch PetscCall(DMLabelView(label, viewer)); 1709c1cad2e7SMatthew G. Knepley } 17109566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames[l])); 1711c1cad2e7SMatthew G. Knepley } 17129566063dSJacob Faibussowitsch PetscCall(PetscFree(labelNames)); 1713c1cad2e7SMatthew G. Knepley } 171434aa8a36SMatthew G. Knepley /* If no fields are specified, people do not want to see adjacency */ 171534aa8a36SMatthew G. Knepley if (dm->Nf) { 171634aa8a36SMatthew G. Knepley PetscInt f; 171734aa8a36SMatthew G. Knepley 171834aa8a36SMatthew G. Knepley for (f = 0; f < dm->Nf; ++f) { 171934aa8a36SMatthew G. Knepley const char *name; 172034aa8a36SMatthew G. Knepley 17219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName(dm->fields[f].disc, &name)); 17229566063dSJacob Faibussowitsch if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name)); 17239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 17249566063dSJacob Faibussowitsch if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer)); 172534aa8a36SMatthew G. Knepley if (dm->fields[f].adjacency[0]) { 17269566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n")); 17279566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n")); 172834aa8a36SMatthew G. Knepley } else { 17299566063dSJacob Faibussowitsch if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n")); 17309566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n")); 173134aa8a36SMatthew G. Knepley } 17329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 173334aa8a36SMatthew G. Knepley } 173434aa8a36SMatthew G. Knepley } 17359566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &cdm)); 17368e7ff633SMatthew G. Knepley if (cdm) { 17379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 17389f4ada15SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n")); 17399566063dSJacob Faibussowitsch PetscCall(DMPlexView_Ascii(cdm, viewer)); 17409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 17418e7ff633SMatthew G. Knepley } 1742552f7358SJed Brown } 17433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1744552f7358SJed Brown } 1745552f7358SJed Brown 1746d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) 1747d71ae5a4SJacob Faibussowitsch { 1748e5c487bfSMatthew G. Knepley DMPolytopeType ct; 1749e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1750a12d352dSMatthew G. Knepley PetscInt cdim; 1751e5c487bfSMatthew G. Knepley 1752e5c487bfSMatthew G. Knepley PetscFunctionBegin; 17539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 17549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cell, &ct)); 17559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 1756e5c487bfSMatthew G. Knepley switch (ct) { 1757a12d352dSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 1758a12d352dSMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 1759a12d352dSMatthew G. Knepley switch (cdim) { 17609371c9d4SSatish Balay case 1: { 1761a12d352dSMatthew G. Knepley const PetscReal y = 0.5; /* TODO Put it in the middle of the viewport */ 1762a12d352dSMatthew G. Knepley const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */ 1763a12d352dSMatthew G. Knepley 17649566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK)); 17659566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK)); 17669566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK)); 17679371c9d4SSatish Balay } break; 17689371c9d4SSatish Balay case 2: { 1769a12d352dSMatthew G. Knepley const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1])); 1770a12d352dSMatthew G. Knepley const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0])); 1771a12d352dSMatthew G. Knepley const PetscReal l = 0.1 / PetscSqrtReal(dx * dx + dy * dy); 1772a12d352dSMatthew G. Knepley 17739566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17749566063dSJacob 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)); 17759566063dSJacob 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)); 17769371c9d4SSatish Balay } break; 1777d71ae5a4SJacob Faibussowitsch default: 1778d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim); 1779a12d352dSMatthew G. Knepley } 1780a12d352dSMatthew G. Knepley break; 1781e5c487bfSMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 17829371c9d4SSatish 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)); 17839566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17849566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17859566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1786e5c487bfSMatthew G. Knepley break; 1787e5c487bfSMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 17889371c9d4SSatish 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)); 17899371c9d4SSatish 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)); 17909566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17919566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 17929566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 17939566063dSJacob Faibussowitsch PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 1794e5c487bfSMatthew G. Knepley break; 17959f4ada15SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 17969f4ada15SMatthew 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)); 17979f4ada15SMatthew 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)); 17989f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK)); 17999f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK)); 18009f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK)); 18019f4ada15SMatthew G. Knepley PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK)); 18029f4ada15SMatthew G. Knepley break; 1803d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_FV_GHOST: 1804d71ae5a4SJacob Faibussowitsch break; 1805d71ae5a4SJacob Faibussowitsch default: 1806d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1807e5c487bfSMatthew G. Knepley } 18083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1809e5c487bfSMatthew G. Knepley } 1810e5c487bfSMatthew G. Knepley 1811c5aedaa3SMatthew G. Knepley static PetscErrorCode DrawPolygon_Private(DM dm, PetscDraw draw, PetscInt cell, PetscInt Nv, const PetscReal refVertices[], const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1812d71ae5a4SJacob Faibussowitsch { 1813e5c487bfSMatthew G. Knepley PetscReal centroid[2] = {0., 0.}; 1814e5c487bfSMatthew G. Knepley PetscMPIInt rank; 1815*6497c311SBarry Smith PetscMPIInt fillColor; 1816e5c487bfSMatthew G. Knepley 1817e5c487bfSMatthew G. Knepley PetscFunctionBegin; 18189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1819e5c487bfSMatthew G. Knepley fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2; 1820c5aedaa3SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 1821c5aedaa3SMatthew G. Knepley centroid[0] += PetscRealPart(coords[v * 2 + 0]) / Nv; 1822c5aedaa3SMatthew G. Knepley centroid[1] += PetscRealPart(coords[v * 2 + 1]) / Nv; 18239371c9d4SSatish Balay } 1824c5aedaa3SMatthew G. Knepley for (PetscInt e = 0; e < Nv; ++e) { 1825e5c487bfSMatthew G. Knepley refCoords[0] = refVertices[e * 2 + 0]; 1826e5c487bfSMatthew G. Knepley refCoords[1] = refVertices[e * 2 + 1]; 1827c5aedaa3SMatthew G. Knepley for (PetscInt d = 1; d <= edgeDiv; ++d) { 1828c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % Nv * 2 + 0] - refCoords[0]) * d / edgeDiv; 1829c5aedaa3SMatthew G. Knepley refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % Nv * 2 + 1] - refCoords[1]) * d / edgeDiv; 1830e5c487bfSMatthew G. Knepley } 18319566063dSJacob Faibussowitsch PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords)); 1832c5aedaa3SMatthew G. Knepley for (PetscInt d = 0; d < edgeDiv; ++d) { 18339566063dSJacob 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)); 18349566063dSJacob 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)); 1835e5c487bfSMatthew G. Knepley } 1836e5c487bfSMatthew G. Knepley } 1837c5aedaa3SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1838c5aedaa3SMatthew G. Knepley } 1839c5aedaa3SMatthew G. Knepley 1840c5aedaa3SMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) 1841c5aedaa3SMatthew G. Knepley { 1842c5aedaa3SMatthew G. Knepley DMPolytopeType ct; 1843c5aedaa3SMatthew G. Knepley 1844c5aedaa3SMatthew G. Knepley PetscFunctionBegin; 1845c5aedaa3SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, cell, &ct)); 1846c5aedaa3SMatthew G. Knepley switch (ct) { 1847c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: { 1848c5aedaa3SMatthew G. Knepley PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.}; 1849c5aedaa3SMatthew G. Knepley 1850c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 3, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 1851c5aedaa3SMatthew G. Knepley } break; 1852c5aedaa3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: { 1853c5aedaa3SMatthew G. Knepley PetscReal refVertices[8] = {-1., -1., 1., -1., 1., 1., -1., 1.}; 1854c5aedaa3SMatthew G. Knepley 1855c5aedaa3SMatthew G. Knepley PetscCall(DrawPolygon_Private(dm, draw, cell, 4, refVertices, coords, edgeDiv, refCoords, edgeCoords)); 18569371c9d4SSatish Balay } break; 1857d71ae5a4SJacob Faibussowitsch default: 1858d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]); 1859e5c487bfSMatthew G. Knepley } 18603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1861e5c487bfSMatthew G. Knepley } 1862e5c487bfSMatthew G. Knepley 1863d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) 1864d71ae5a4SJacob Faibussowitsch { 1865e412dcbdSMatthew G. Knepley PetscDraw draw; 1866e412dcbdSMatthew G. Knepley DM cdm; 1867e412dcbdSMatthew G. Knepley PetscSection coordSection; 1868e412dcbdSMatthew G. Knepley Vec coordinates; 1869c9c77995SMatthew G. Knepley PetscReal xyl[3], xyr[3]; 1870e5c487bfSMatthew G. Knepley PetscReal *refCoords, *edgeCoords; 1871c5aedaa3SMatthew G. Knepley PetscBool isnull, drawAffine; 1872c5aedaa3SMatthew G. Knepley PetscInt dim, vStart, vEnd, cStart, cEnd, c, cDegree, edgeDiv; 1873e412dcbdSMatthew G. Knepley 1874e412dcbdSMatthew G. Knepley PetscFunctionBegin; 18759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 187663a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim); 1877c5aedaa3SMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, &cDegree)); 1878c5aedaa3SMatthew G. Knepley drawAffine = cDegree > 1 ? PETSC_FALSE : PETSC_TRUE; 1879c5aedaa3SMatthew G. Knepley edgeDiv = cDegree + 1; 18809566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL)); 18819566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords)); 18829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 18839566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(cdm, &coordSection)); 18849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 18859566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 18869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1887e412dcbdSMatthew G. Knepley 18889566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18899566063dSJacob Faibussowitsch PetscCall(PetscDrawIsNull(draw, &isnull)); 18903ba16761SJacob Faibussowitsch if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 18919566063dSJacob Faibussowitsch PetscCall(PetscDrawSetTitle(draw, "Mesh")); 1892e412dcbdSMatthew G. Knepley 1893c9c77995SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, xyl, xyr)); 18949566063dSJacob Faibussowitsch PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1])); 18959566063dSJacob Faibussowitsch PetscCall(PetscDrawClear(draw)); 1896e412dcbdSMatthew G. Knepley 1897cf3064d3SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 1898cf3064d3SMatthew G. Knepley PetscScalar *coords = NULL; 1899c9c77995SMatthew G. Knepley const PetscScalar *coords_arr; 1900ba2698f1SMatthew G. Knepley PetscInt numCoords; 1901c9c77995SMatthew G. Knepley PetscBool isDG; 1902cf3064d3SMatthew G. Knepley 1903c9c77995SMatthew G. Knepley PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 19041baa6e33SBarry Smith if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords)); 19051baa6e33SBarry Smith else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords)); 1906c9c77995SMatthew G. Knepley PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords)); 1907cf3064d3SMatthew G. Knepley } 19089566063dSJacob Faibussowitsch if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords)); 19099566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 19109566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 19119566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 19123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1913e412dcbdSMatthew G. Knepley } 1914e412dcbdSMatthew G. Knepley 1915e44f6aebSMatthew G. Knepley static PetscErrorCode DMPlexCreateHighOrderSurrogate_Internal(DM dm, DM *hdm) 1916e44f6aebSMatthew G. Knepley { 1917e44f6aebSMatthew G. Knepley DM odm = dm, rdm = dm, cdm; 1918e44f6aebSMatthew G. Knepley PetscFE fe; 1919e44f6aebSMatthew G. Knepley PetscSpace sp; 1920e44f6aebSMatthew G. Knepley PetscClassId id; 1921e44f6aebSMatthew G. Knepley PetscInt degree; 1922e44f6aebSMatthew G. Knepley PetscBool hoView = PETSC_TRUE; 1923e44f6aebSMatthew G. Knepley 1924e44f6aebSMatthew G. Knepley PetscFunctionBegin; 1925e44f6aebSMatthew G. Knepley PetscObjectOptionsBegin((PetscObject)dm); 1926e44f6aebSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_high_order_view", "Subsample to view meshes with high order coordinates", "DMPlexCreateHighOrderSurrogate_Internal", hoView, &hoView, NULL)); 1927e44f6aebSMatthew G. Knepley PetscOptionsEnd(); 1928e44f6aebSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dm)); 1929e44f6aebSMatthew G. Knepley *hdm = dm; 1930e44f6aebSMatthew G. Knepley if (!hoView) PetscFunctionReturn(PETSC_SUCCESS); 1931e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 1932e44f6aebSMatthew G. Knepley PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe)); 1933e44f6aebSMatthew G. Knepley PetscCall(PetscObjectGetClassId((PetscObject)fe, &id)); 1934e44f6aebSMatthew G. Knepley if (id != PETSCFE_CLASSID) PetscFunctionReturn(PETSC_SUCCESS); 1935e44f6aebSMatthew G. Knepley PetscCall(PetscFEGetBasisSpace(fe, &sp)); 1936e44f6aebSMatthew G. Knepley PetscCall(PetscSpaceGetDegree(sp, °ree, NULL)); 1937e44f6aebSMatthew G. Knepley for (PetscInt r = 0, rd = PetscCeilReal(((PetscReal)degree) / 2.); r < (PetscInt)PetscCeilReal(PetscLog2Real(degree)); ++r, rd = PetscCeilReal(((PetscReal)rd) / 2.)) { 1938e44f6aebSMatthew G. Knepley DM cdm, rcdm; 1939e44f6aebSMatthew G. Knepley Mat In; 1940e44f6aebSMatthew G. Knepley Vec cl, rcl; 1941e44f6aebSMatthew G. Knepley 1942e44f6aebSMatthew G. Knepley PetscCall(DMRefine(odm, PetscObjectComm((PetscObject)odm), &rdm)); 1943c5aedaa3SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(rdm, rd, PETSC_FALSE, NULL)); 1944e44f6aebSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)rdm, "Refined Mesh with Linear Coordinates")); 1945e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(odm, &cdm)); 1946e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(rdm, &rcdm)); 1947e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(odm, &cl)); 1948e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(rdm, &rcl)); 1949e44f6aebSMatthew G. Knepley PetscCall(DMSetCoarseDM(rcdm, cdm)); 1950e44f6aebSMatthew G. Knepley PetscCall(DMCreateInterpolation(cdm, rcdm, &In, NULL)); 1951e44f6aebSMatthew G. Knepley PetscCall(MatMult(In, cl, rcl)); 1952e44f6aebSMatthew G. Knepley PetscCall(MatDestroy(&In)); 1953e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(rdm, rcl)); 1954e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&odm)); 1955e44f6aebSMatthew G. Knepley odm = rdm; 1956e44f6aebSMatthew G. Knepley } 1957e44f6aebSMatthew G. Knepley *hdm = rdm; 1958e44f6aebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1959e44f6aebSMatthew G. Knepley } 1960e44f6aebSMatthew G. Knepley 19611e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 19621e50132fSMatthew G. Knepley #include <exodusII.h> 19636823f3c5SBlaise Bourdin #include <petscviewerexodusii.h> 19641e50132fSMatthew G. Knepley #endif 19651e50132fSMatthew G. Knepley 1966d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 1967d71ae5a4SJacob Faibussowitsch { 19685f34f2dcSJed Brown PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns; 1969002a2709SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 1970552f7358SJed Brown 1971552f7358SJed Brown PetscFunctionBegin; 1972552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1973552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis)); 19799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus)); 19805f34f2dcSJed Brown PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns)); 1981552f7358SJed Brown if (iascii) { 19828135c375SStefano Zampini PetscViewerFormat format; 19839566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 19841baa6e33SBarry Smith if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer)); 19851baa6e33SBarry Smith else PetscCall(DMPlexView_Ascii(dm, viewer)); 1986c6ccd67eSMatthew G. Knepley } else if (ishdf5) { 1987c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 19889566063dSJacob Faibussowitsch PetscCall(DMPlexView_HDF5_Internal(dm, viewer)); 1989c6ccd67eSMatthew G. Knepley #else 1990c6ccd67eSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 1991552f7358SJed Brown #endif 1992e412dcbdSMatthew G. Knepley } else if (isvtk) { 19939566063dSJacob Faibussowitsch PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer)); 1994e412dcbdSMatthew G. Knepley } else if (isdraw) { 1995e44f6aebSMatthew G. Knepley DM hdm; 1996e44f6aebSMatthew G. Knepley 1997e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateHighOrderSurrogate_Internal(dm, &hdm)); 1998e44f6aebSMatthew G. Knepley PetscCall(DMPlexView_Draw(hdm, viewer)); 1999e44f6aebSMatthew G. Knepley PetscCall(DMDestroy(&hdm)); 20008135c375SStefano Zampini } else if (isglvis) { 20019566063dSJacob Faibussowitsch PetscCall(DMPlexView_GLVis(dm, viewer)); 20021e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII) 20031e50132fSMatthew G. Knepley } else if (isexodus) { 20046823f3c5SBlaise Bourdin /* 20056823f3c5SBlaise Bourdin exodusII requires that all sets be part of exactly one cell set. 20066823f3c5SBlaise Bourdin If the dm does not have a "Cell Sets" label defined, we create one 2007da81f932SPierre Jolivet with ID 1, containing all cells. 20086823f3c5SBlaise Bourdin Note that if the Cell Sets label is defined but does not cover all cells, 20096823f3c5SBlaise Bourdin we may still have a problem. This should probably be checked here or in the viewer; 20106823f3c5SBlaise Bourdin */ 20116823f3c5SBlaise Bourdin PetscInt numCS; 20129566063dSJacob Faibussowitsch PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS)); 20136823f3c5SBlaise Bourdin if (!numCS) { 20141e50132fSMatthew G. Knepley PetscInt cStart, cEnd, c; 20159566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Cell Sets")); 20169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 20179566063dSJacob Faibussowitsch for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1)); 20186823f3c5SBlaise Bourdin } 20199566063dSJacob Faibussowitsch PetscCall(DMView_PlexExodusII(dm, viewer)); 20201e50132fSMatthew G. Knepley #endif 20215f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS) 20225f34f2dcSJed Brown } else if (iscgns) { 20235f34f2dcSJed Brown PetscCall(DMView_PlexCGNS(dm, viewer)); 20245f34f2dcSJed Brown #endif 20251baa6e33SBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name); 2026cb3ba0daSMatthew G. Knepley /* Optionally view the partition */ 20279566063dSJacob Faibussowitsch PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg)); 2028cb3ba0daSMatthew G. Knepley if (flg) { 2029cb3ba0daSMatthew G. Knepley Vec ranks; 20309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateRankField(dm, &ranks)); 20319566063dSJacob Faibussowitsch PetscCall(VecView(ranks, viewer)); 20329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ranks)); 2033cb3ba0daSMatthew G. Knepley } 2034002a2709SMatthew G. Knepley /* Optionally view a label */ 20359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg)); 2036002a2709SMatthew G. Knepley if (flg) { 2037002a2709SMatthew G. Knepley DMLabel label; 2038002a2709SMatthew G. Knepley Vec val; 2039002a2709SMatthew G. Knepley 20409566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 204128b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name); 20429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateLabelField(dm, label, &val)); 20439566063dSJacob Faibussowitsch PetscCall(VecView(val, viewer)); 20449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&val)); 2045002a2709SMatthew G. Knepley } 20463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2047552f7358SJed Brown } 2048552f7358SJed Brown 20497f96f51bSksagiyam /*@ 2050a1cb98faSBarry Smith DMPlexTopologyView - Saves a `DMPLEX` topology into a file 20517f96f51bSksagiyam 205220f4b53cSBarry Smith Collective 20537f96f51bSksagiyam 20547f96f51bSksagiyam Input Parameters: 2055a1cb98faSBarry Smith + dm - The `DM` whose topology is to be saved 2056a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in 20577f96f51bSksagiyam 20587f96f51bSksagiyam Level: advanced 20597f96f51bSksagiyam 20601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer` 20617f96f51bSksagiyam @*/ 2062d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) 2063d71ae5a4SJacob Faibussowitsch { 20647f96f51bSksagiyam PetscBool ishdf5; 20657f96f51bSksagiyam 20667f96f51bSksagiyam PetscFunctionBegin; 20677f96f51bSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 20687f96f51bSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 20699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 20709566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20717f96f51bSksagiyam if (ishdf5) { 20727f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5) 20737f96f51bSksagiyam PetscViewerFormat format; 20749566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 20757f96f51bSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 20767f96f51bSksagiyam IS globalPointNumbering; 20777f96f51bSksagiyam 20789566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 20799566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer)); 20809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 208198921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 20827f96f51bSksagiyam #else 20837f96f51bSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 20847f96f51bSksagiyam #endif 20857f96f51bSksagiyam } 20869566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0)); 20873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20887f96f51bSksagiyam } 20897f96f51bSksagiyam 209077b8e257Sksagiyam /*@ 2091a1cb98faSBarry Smith DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file 209277b8e257Sksagiyam 209320f4b53cSBarry Smith Collective 209477b8e257Sksagiyam 209577b8e257Sksagiyam Input Parameters: 2096a1cb98faSBarry Smith + dm - The `DM` whose coordinates are to be saved 2097a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 209877b8e257Sksagiyam 209977b8e257Sksagiyam Level: advanced 210077b8e257Sksagiyam 21011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer` 210277b8e257Sksagiyam @*/ 2103d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) 2104d71ae5a4SJacob Faibussowitsch { 210577b8e257Sksagiyam PetscBool ishdf5; 210677b8e257Sksagiyam 210777b8e257Sksagiyam PetscFunctionBegin; 210877b8e257Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 210977b8e257Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21119566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 211277b8e257Sksagiyam if (ishdf5) { 211377b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5) 211477b8e257Sksagiyam PetscViewerFormat format; 21159566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 211677b8e257Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21179566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer)); 2118fe28d297SMatthew Knepley } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]); 211977b8e257Sksagiyam #else 212077b8e257Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 212177b8e257Sksagiyam #endif 212277b8e257Sksagiyam } 21239566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0)); 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212577b8e257Sksagiyam } 212677b8e257Sksagiyam 2127bd6565f1Sksagiyam /*@ 2128a1cb98faSBarry Smith DMPlexLabelsView - Saves `DMPLEX` labels into a file 2129bd6565f1Sksagiyam 213020f4b53cSBarry Smith Collective 2131bd6565f1Sksagiyam 2132bd6565f1Sksagiyam Input Parameters: 2133a1cb98faSBarry Smith + dm - The `DM` whose labels are to be saved 2134a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving 2135bd6565f1Sksagiyam 2136bd6565f1Sksagiyam Level: advanced 2137bd6565f1Sksagiyam 21381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer` 2139bd6565f1Sksagiyam @*/ 2140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) 2141d71ae5a4SJacob Faibussowitsch { 2142bd6565f1Sksagiyam PetscBool ishdf5; 2143bd6565f1Sksagiyam 2144bd6565f1Sksagiyam PetscFunctionBegin; 2145bd6565f1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2146bd6565f1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0)); 2149bd6565f1Sksagiyam if (ishdf5) { 2150bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5) 2151bd6565f1Sksagiyam IS globalPointNumbering; 2152bd6565f1Sksagiyam PetscViewerFormat format; 2153bd6565f1Sksagiyam 21549566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2155bd6565f1Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 21569566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering)); 21579566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer)); 21589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&globalPointNumbering)); 215998921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2160bd6565f1Sksagiyam #else 2161bd6565f1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2162bd6565f1Sksagiyam #endif 2163bd6565f1Sksagiyam } 21649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0)); 21653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2166bd6565f1Sksagiyam } 2167bd6565f1Sksagiyam 2168021affd3Sksagiyam /*@ 2169a1cb98faSBarry Smith DMPlexSectionView - Saves a section associated with a `DMPLEX` 2170021affd3Sksagiyam 217120f4b53cSBarry Smith Collective 2172021affd3Sksagiyam 2173021affd3Sksagiyam Input Parameters: 2174a1cb98faSBarry Smith + dm - The `DM` that contains the topology on which the section to be saved is defined 2175a1cb98faSBarry Smith . viewer - The `PetscViewer` for saving 21760318f8a0SStefano Zampini - sectiondm - The `DM` that contains the section to be saved, can be `NULL` 2177021affd3Sksagiyam 2178021affd3Sksagiyam Level: advanced 2179021affd3Sksagiyam 2180021affd3Sksagiyam Notes: 2181420bcc1bSBarry 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. 2182021affd3Sksagiyam 21830318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2184021affd3Sksagiyam 21851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer` 2186021affd3Sksagiyam @*/ 2187d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) 2188d71ae5a4SJacob Faibussowitsch { 2189021affd3Sksagiyam PetscBool ishdf5; 2190021affd3Sksagiyam 2191021affd3Sksagiyam PetscFunctionBegin; 2192021affd3Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2193021affd3Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 21940318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2195021affd3Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 21969566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 21979566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0)); 2198021affd3Sksagiyam if (ishdf5) { 2199021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5) 22009566063dSJacob Faibussowitsch PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm)); 2201021affd3Sksagiyam #else 2202021affd3Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2203021affd3Sksagiyam #endif 2204021affd3Sksagiyam } 22059566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0)); 22063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2207021affd3Sksagiyam } 2208021affd3Sksagiyam 22093e97647fSksagiyam /*@ 22103e97647fSksagiyam DMPlexGlobalVectorView - Saves a global vector 22113e97647fSksagiyam 221220f4b53cSBarry Smith Collective 22133e97647fSksagiyam 22143e97647fSksagiyam Input Parameters: 2215a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2216a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22170318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 22183e97647fSksagiyam - vec - The global vector to be saved 22193e97647fSksagiyam 22203e97647fSksagiyam Level: advanced 22213e97647fSksagiyam 22223e97647fSksagiyam Notes: 22230318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 22243e97647fSksagiyam 222560225df5SJacob Faibussowitsch Calling sequence: 2226a1cb98faSBarry Smith .vb 2227a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2228a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2229a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2230a1cb98faSBarry Smith DMClone(dm, §iondm); 2231a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2232a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2233a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2234a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2235a1cb98faSBarry Smith PetscSectionSetUp(section); 2236a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2237a1cb98faSBarry Smith PetscSectionDestroy(§ion); 2238a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2239a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2240a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2241a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2242a1cb98faSBarry Smith DMPlexGlobalVectorView(dm, viewer, sectiondm, vec); 2243a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2244a1cb98faSBarry Smith DMDestroy(§iondm); 2245a1cb98faSBarry Smith DMDestroy(&dm); 2246a1cb98faSBarry Smith .ve 22473e97647fSksagiyam 22481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 22493e97647fSksagiyam @*/ 2250d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2251d71ae5a4SJacob Faibussowitsch { 22523e97647fSksagiyam PetscBool ishdf5; 22533e97647fSksagiyam 22543e97647fSksagiyam PetscFunctionBegin; 22553e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22563e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 22570318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 22583e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 22593e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 22603e97647fSksagiyam /* Check consistency */ 22613e97647fSksagiyam { 22623e97647fSksagiyam PetscSection section; 22633e97647fSksagiyam PetscBool includesConstraints; 22643e97647fSksagiyam PetscInt m, m1; 22653e97647fSksagiyam 22669566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 22679566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 22689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 22699566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 22709566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 227163a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 22723e97647fSksagiyam } 22739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 22749566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22753e97647fSksagiyam if (ishdf5) { 22763e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 22779566063dSJacob Faibussowitsch PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 22783e97647fSksagiyam #else 22793e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 22803e97647fSksagiyam #endif 22813e97647fSksagiyam } 22829566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0)); 22833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22843e97647fSksagiyam } 22853e97647fSksagiyam 22863e97647fSksagiyam /*@ 22873e97647fSksagiyam DMPlexLocalVectorView - Saves a local vector 22883e97647fSksagiyam 228920f4b53cSBarry Smith Collective 22903e97647fSksagiyam 22913e97647fSksagiyam Input Parameters: 2292a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2293a1cb98faSBarry Smith . viewer - The `PetscViewer` to save data with 22940318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which `vec` is defined, can be `NULL` 22953e97647fSksagiyam - vec - The local vector to be saved 22963e97647fSksagiyam 22973e97647fSksagiyam Level: advanced 22983e97647fSksagiyam 2299a1cb98faSBarry Smith Note: 23000318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 23013e97647fSksagiyam 230260225df5SJacob Faibussowitsch Calling sequence: 2303a1cb98faSBarry Smith .vb 2304a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2305a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2306a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2307a1cb98faSBarry Smith DMClone(dm, §iondm); 2308a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2309a1cb98faSBarry Smith PetscSectionCreate(PETSC_COMM_WORLD, §ion); 2310a1cb98faSBarry Smith DMPlexGetChart(sectiondm, &pStart, &pEnd); 2311a1cb98faSBarry Smith PetscSectionSetChart(section, pStart, pEnd); 2312a1cb98faSBarry Smith PetscSectionSetUp(section); 2313a1cb98faSBarry Smith DMSetLocalSection(sectiondm, section); 2314a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2315a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2316a1cb98faSBarry Smith DMPlexTopologyView(dm, viewer); 2317a1cb98faSBarry Smith DMPlexSectionView(dm, viewer, sectiondm); 2318a1cb98faSBarry Smith DMPlexLocalVectorView(dm, viewer, sectiondm, vec); 2319a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2320a1cb98faSBarry Smith DMDestroy(§iondm); 2321a1cb98faSBarry Smith DMDestroy(&dm); 2322a1cb98faSBarry Smith .ve 23233e97647fSksagiyam 23241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()` 23253e97647fSksagiyam @*/ 2326d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) 2327d71ae5a4SJacob Faibussowitsch { 23283e97647fSksagiyam PetscBool ishdf5; 23293e97647fSksagiyam 23303e97647fSksagiyam PetscFunctionBegin; 23313e97647fSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23323e97647fSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23330318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 23343e97647fSksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 23353e97647fSksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 4); 23363e97647fSksagiyam /* Check consistency */ 23373e97647fSksagiyam { 23383e97647fSksagiyam PetscSection section; 23393e97647fSksagiyam PetscBool includesConstraints; 23403e97647fSksagiyam PetscInt m, m1; 23413e97647fSksagiyam 23429566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 23439566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 23449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 23459566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 23469566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 234763a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 23483e97647fSksagiyam } 23499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 23509566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23513e97647fSksagiyam if (ishdf5) { 23523e97647fSksagiyam #if defined(PETSC_HAVE_HDF5) 23539566063dSJacob Faibussowitsch PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec)); 23543e97647fSksagiyam #else 23553e97647fSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 23563e97647fSksagiyam #endif 23573e97647fSksagiyam } 23589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0)); 23593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23603e97647fSksagiyam } 23613e97647fSksagiyam 2362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 2363d71ae5a4SJacob Faibussowitsch { 2364d4f5a9a0SVaclav Hapla PetscBool ishdf5; 23652c40f234SMatthew G. Knepley 23662c40f234SMatthew G. Knepley PetscFunctionBegin; 23672c40f234SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23682c40f234SMatthew G. Knepley PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 23699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 2370d4f5a9a0SVaclav Hapla if (ishdf5) { 23712c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 23729c48423bSVaclav Hapla PetscViewerFormat format; 23739566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23749c48423bSVaclav Hapla if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) { 23759566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer)); 2376509517efSVaclav Hapla } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 23779566063dSJacob Faibussowitsch PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer)); 237898921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 23793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23802c40f234SMatthew G. Knepley #else 23812c40f234SMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2382552f7358SJed Brown #endif 238398921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name); 2384552f7358SJed Brown } 2385552f7358SJed Brown 2386ea8e1828Sksagiyam /*@ 2387a1cb98faSBarry Smith DMPlexTopologyLoad - Loads a topology into a `DMPLEX` 2388ea8e1828Sksagiyam 238920f4b53cSBarry Smith Collective 2390ea8e1828Sksagiyam 2391ea8e1828Sksagiyam Input Parameters: 2392a1cb98faSBarry Smith + dm - The `DM` into which the topology is loaded 2393a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology 2394ea8e1828Sksagiyam 23952fe279fdSBarry Smith Output Parameter: 23962c9a7b26SBarry 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; 23972c9a7b26SBarry Smith `NULL` if unneeded 2398dec9e869Sksagiyam 2399ea8e1828Sksagiyam Level: advanced 2400ea8e1828Sksagiyam 24011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2402a1cb98faSBarry Smith `PetscViewer`, `PetscSF` 2403ea8e1828Sksagiyam @*/ 2404d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) 2405d71ae5a4SJacob Faibussowitsch { 2406ea8e1828Sksagiyam PetscBool ishdf5; 2407ea8e1828Sksagiyam 2408ea8e1828Sksagiyam PetscFunctionBegin; 2409ea8e1828Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2410ea8e1828Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24114f572ea9SToby Isaac if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3); 24129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 2414ea8e1828Sksagiyam if (ishdf5) { 2415ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5) 2416ea8e1828Sksagiyam PetscViewerFormat format; 24179566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2418ea8e1828Sksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24199566063dSJacob Faibussowitsch PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 242098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2421ea8e1828Sksagiyam #else 2422ea8e1828Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2423ea8e1828Sksagiyam #endif 2424ea8e1828Sksagiyam } 24259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0)); 24263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2427ea8e1828Sksagiyam } 2428ea8e1828Sksagiyam 24293e701f1cSksagiyam /*@ 2430a1cb98faSBarry Smith DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX` 24313e701f1cSksagiyam 243220f4b53cSBarry Smith Collective 24333e701f1cSksagiyam 24343e701f1cSksagiyam Input Parameters: 2435a1cb98faSBarry Smith + dm - The `DM` into which the coordinates are loaded 2436a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved coordinates 2437a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer 24383e701f1cSksagiyam 24393e701f1cSksagiyam Level: advanced 24403e701f1cSksagiyam 24411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2442a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 24433e701f1cSksagiyam @*/ 2444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2445d71ae5a4SJacob Faibussowitsch { 24463e701f1cSksagiyam PetscBool ishdf5; 24473e701f1cSksagiyam 24483e701f1cSksagiyam PetscFunctionBegin; 24493e701f1cSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24503e701f1cSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2451c9ad657eSksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24539566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24543e701f1cSksagiyam if (ishdf5) { 24553e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5) 24563e701f1cSksagiyam PetscViewerFormat format; 24579566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 24583e701f1cSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 24599566063dSJacob Faibussowitsch PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 246098921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 24613e701f1cSksagiyam #else 24623e701f1cSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 24633e701f1cSksagiyam #endif 24643e701f1cSksagiyam } 24659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0)); 24663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24673e701f1cSksagiyam } 24683e701f1cSksagiyam 2469b08ad5deSksagiyam /*@ 2470a1cb98faSBarry Smith DMPlexLabelsLoad - Loads labels into a `DMPLEX` 2471b08ad5deSksagiyam 247220f4b53cSBarry Smith Collective 2473b08ad5deSksagiyam 2474b08ad5deSksagiyam Input Parameters: 2475a1cb98faSBarry Smith + dm - The `DM` into which the labels are loaded 2476a1cb98faSBarry Smith . viewer - The `PetscViewer` for the saved labels 247720f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer 2478b08ad5deSksagiyam 2479b08ad5deSksagiyam Level: advanced 2480b08ad5deSksagiyam 2481a1cb98faSBarry Smith Note: 2482dc9a610eSPierre Jolivet The `PetscSF` argument must not be `NULL` if the `DM` is distributed, otherwise an error occurs. 2483e6368b79SVaclav Hapla 24841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`, 2485a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 2486b08ad5deSksagiyam @*/ 2487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) 2488d71ae5a4SJacob Faibussowitsch { 2489b08ad5deSksagiyam PetscBool ishdf5; 2490b08ad5deSksagiyam 2491b08ad5deSksagiyam PetscFunctionBegin; 2492b08ad5deSksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2493b08ad5deSksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 2494e6368b79SVaclav Hapla if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3); 24959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 24969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 2497b08ad5deSksagiyam if (ishdf5) { 2498b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5) 2499b08ad5deSksagiyam PetscViewerFormat format; 2500b08ad5deSksagiyam 25019566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2502b08ad5deSksagiyam if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) { 25039566063dSJacob Faibussowitsch PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF)); 250498921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]); 2505b08ad5deSksagiyam #else 2506b08ad5deSksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2507b08ad5deSksagiyam #endif 2508b08ad5deSksagiyam } 25099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0)); 25103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2511b08ad5deSksagiyam } 2512b08ad5deSksagiyam 2513f84dd6b4Sksagiyam /*@ 2514a1cb98faSBarry Smith DMPlexSectionLoad - Loads section into a `DMPLEX` 2515f84dd6b4Sksagiyam 251620f4b53cSBarry Smith Collective 2517f84dd6b4Sksagiyam 2518f84dd6b4Sksagiyam Input Parameters: 2519a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2520a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk section (sectionA) 25210318f8a0SStefano Zampini . sectiondm - The `DM` into which the on-disk section (sectionA) is migrated, can be `NULL` 2522a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer 2523f84dd6b4Sksagiyam 2524a4e35b19SJacob Faibussowitsch Output Parameters: 252520f4b53cSBarry 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) 252620f4b53cSBarry 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) 2527f84dd6b4Sksagiyam 2528f84dd6b4Sksagiyam Level: advanced 2529f84dd6b4Sksagiyam 2530f84dd6b4Sksagiyam Notes: 253120f4b53cSBarry 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. 2532f84dd6b4Sksagiyam 25330318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 2534f84dd6b4Sksagiyam 253520f4b53cSBarry 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. 2536f84dd6b4Sksagiyam 2537f84dd6b4Sksagiyam Example using 2 processes: 2538a1cb98faSBarry Smith .vb 2539a1cb98faSBarry Smith NX (number of points on dm): 4 2540a1cb98faSBarry Smith sectionA : the on-disk section 2541a1cb98faSBarry Smith vecA : a vector associated with sectionA 2542a1cb98faSBarry Smith sectionB : sectiondm's local section constructed in this function 2543a1cb98faSBarry Smith vecB (local) : a vector associated with sectiondm's local section 2544a1cb98faSBarry Smith vecB (global) : a vector associated with sectiondm's global section 2545f84dd6b4Sksagiyam 2546a1cb98faSBarry Smith rank 0 rank 1 2547a1cb98faSBarry Smith vecA (global) : [.0 .4 .1 | .2 .3] <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad() 2548a1cb98faSBarry Smith sectionA->atlasOff : 0 2 | 1 <- loaded in PetscSectionLoad() 2549a1cb98faSBarry Smith sectionA->atlasDof : 1 3 | 1 <- loaded in PetscSectionLoad() 2550a1cb98faSBarry Smith sectionA's global point numbers: 0 2 | 3 <- loaded in DMPlexSectionLoad() 2551a1cb98faSBarry Smith [0, NX) : 0 1 | 2 3 <- conceptual partition used in globalToLocalPointSF 2552a1cb98faSBarry Smith sectionB's global point numbers: 0 1 3 | 3 2 <- associated with [0, NX) by globalToLocalPointSF 2553a1cb98faSBarry Smith sectionB->atlasDof : 1 0 1 | 1 3 2554a1cb98faSBarry Smith sectionB->atlasOff (no perm) : 0 1 1 | 0 1 2555a1cb98faSBarry Smith vecB (local) : [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF 2556a1cb98faSBarry Smith vecB (global) : [.0 .4 | .1 .2 .3] <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF 2557a1cb98faSBarry Smith .ve 2558a1cb98faSBarry Smith where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0. 2559a1cb98faSBarry Smith 25601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer` 2561f84dd6b4Sksagiyam @*/ 2562d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) 2563d71ae5a4SJacob Faibussowitsch { 2564f84dd6b4Sksagiyam PetscBool ishdf5; 2565f84dd6b4Sksagiyam 2566f84dd6b4Sksagiyam PetscFunctionBegin; 2567f84dd6b4Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2568f84dd6b4Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 25690318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 2570f84dd6b4Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 2571f84dd6b4Sksagiyam PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4); 25724f572ea9SToby Isaac if (globalDofSF) PetscAssertPointer(globalDofSF, 5); 25734f572ea9SToby Isaac if (localDofSF) PetscAssertPointer(localDofSF, 6); 25749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25759566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 2576f84dd6b4Sksagiyam if (ishdf5) { 2577f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5) 25789566063dSJacob Faibussowitsch PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF)); 2579f84dd6b4Sksagiyam #else 2580f84dd6b4Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 2581f84dd6b4Sksagiyam #endif 2582f84dd6b4Sksagiyam } 25839566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0)); 25843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2585f84dd6b4Sksagiyam } 2586f84dd6b4Sksagiyam 25878be3dfe1Sksagiyam /*@ 25888be3dfe1Sksagiyam DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector 25898be3dfe1Sksagiyam 259020f4b53cSBarry Smith Collective 25918be3dfe1Sksagiyam 25928be3dfe1Sksagiyam Input Parameters: 2593a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2594a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 25950318f8a0SStefano Zampini . sectiondm - The `DM` that contains the global section on which vec is defined, can be `NULL` 2596a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 25978be3dfe1Sksagiyam - vec - The global vector to set values of 25988be3dfe1Sksagiyam 25998be3dfe1Sksagiyam Level: advanced 26008be3dfe1Sksagiyam 26018be3dfe1Sksagiyam Notes: 26020318f8a0SStefano Zampini In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 26038be3dfe1Sksagiyam 260460225df5SJacob Faibussowitsch Calling sequence: 2605a1cb98faSBarry Smith .vb 2606a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2607a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2608a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2609a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2610a1cb98faSBarry Smith DMClone(dm, §iondm); 2611a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2612a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL); 2613a1cb98faSBarry Smith DMGetGlobalVector(sectiondm, &vec); 2614a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2615a1cb98faSBarry Smith DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec); 2616a1cb98faSBarry Smith DMRestoreGlobalVector(sectiondm, &vec); 2617a1cb98faSBarry Smith PetscSFDestroy(&gsf); 2618a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2619a1cb98faSBarry Smith DMDestroy(§iondm); 2620a1cb98faSBarry Smith DMDestroy(&dm); 2621a1cb98faSBarry Smith .ve 26228be3dfe1Sksagiyam 26231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2624a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 26258be3dfe1Sksagiyam @*/ 2626d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2627d71ae5a4SJacob Faibussowitsch { 26288be3dfe1Sksagiyam PetscBool ishdf5; 26298be3dfe1Sksagiyam 26308be3dfe1Sksagiyam PetscFunctionBegin; 26318be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 26328be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 26330318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 26348be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 26358be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 26368be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 26378be3dfe1Sksagiyam /* Check consistency */ 26388be3dfe1Sksagiyam { 26398be3dfe1Sksagiyam PetscSection section; 26408be3dfe1Sksagiyam PetscBool includesConstraints; 26418be3dfe1Sksagiyam PetscInt m, m1; 26428be3dfe1Sksagiyam 26439566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 26449566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(sectiondm, §ion)); 26459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 26469566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 26479566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 264863a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m); 26498be3dfe1Sksagiyam } 26509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 26519566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26528be3dfe1Sksagiyam if (ishdf5) { 26538be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 26549566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 26558be3dfe1Sksagiyam #else 26568be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 26578be3dfe1Sksagiyam #endif 26588be3dfe1Sksagiyam } 26599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0)); 26603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26618be3dfe1Sksagiyam } 26628be3dfe1Sksagiyam 26638be3dfe1Sksagiyam /*@ 26648be3dfe1Sksagiyam DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector 26658be3dfe1Sksagiyam 266620f4b53cSBarry Smith Collective 26678be3dfe1Sksagiyam 26688be3dfe1Sksagiyam Input Parameters: 2669a1cb98faSBarry Smith + dm - The `DM` that represents the topology 2670a1cb98faSBarry Smith . viewer - The `PetscViewer` that represents the on-disk vector data 26710318f8a0SStefano Zampini . sectiondm - The `DM` that contains the local section on which vec is defined, can be `NULL` 2672a1cb98faSBarry Smith . sf - The `PetscSF` that migrates the on-disk vector data into vec 26738be3dfe1Sksagiyam - vec - The local vector to set values of 26748be3dfe1Sksagiyam 26758be3dfe1Sksagiyam Level: advanced 26768be3dfe1Sksagiyam 26778be3dfe1Sksagiyam Notes: 26780318f8a0SStefano Zampini In general `dm` and `sectiondm` are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with `PetscObjectSetName()`. In practice, however, they can be the same object (or in case `sectiondm` is `NULL`) if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name. 26798be3dfe1Sksagiyam 268060225df5SJacob Faibussowitsch Calling sequence: 2681a1cb98faSBarry Smith .vb 2682a1cb98faSBarry Smith DMCreate(PETSC_COMM_WORLD, &dm); 2683a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 2684a1cb98faSBarry Smith PetscObjectSetName((PetscObject)dm, "topologydm_name"); 2685a1cb98faSBarry Smith DMPlexTopologyLoad(dm, viewer, &sfX); 2686a1cb98faSBarry Smith DMClone(dm, §iondm); 2687a1cb98faSBarry Smith PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name"); 2688a1cb98faSBarry Smith DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf); 2689a1cb98faSBarry Smith DMGetLocalVector(sectiondm, &vec); 2690a1cb98faSBarry Smith PetscObjectSetName((PetscObject)vec, "vec_name"); 2691a1cb98faSBarry Smith DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec); 2692a1cb98faSBarry Smith DMRestoreLocalVector(sectiondm, &vec); 2693a1cb98faSBarry Smith PetscSFDestroy(&lsf); 2694a1cb98faSBarry Smith PetscSFDestroy(&sfX); 2695a1cb98faSBarry Smith DMDestroy(§iondm); 2696a1cb98faSBarry Smith DMDestroy(&dm); 2697a1cb98faSBarry Smith .ve 26988be3dfe1Sksagiyam 26991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, 2700a1cb98faSBarry Smith `PetscSF`, `PetscViewer` 27018be3dfe1Sksagiyam @*/ 2702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) 2703d71ae5a4SJacob Faibussowitsch { 27048be3dfe1Sksagiyam PetscBool ishdf5; 27058be3dfe1Sksagiyam 27068be3dfe1Sksagiyam PetscFunctionBegin; 27078be3dfe1Sksagiyam PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 27088be3dfe1Sksagiyam PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 27090318f8a0SStefano Zampini if (!sectiondm) sectiondm = dm; 27108be3dfe1Sksagiyam PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3); 27118be3dfe1Sksagiyam PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4); 27128be3dfe1Sksagiyam PetscValidHeaderSpecific(vec, VEC_CLASSID, 5); 27138be3dfe1Sksagiyam /* Check consistency */ 27148be3dfe1Sksagiyam { 27158be3dfe1Sksagiyam PetscSection section; 27168be3dfe1Sksagiyam PetscBool includesConstraints; 27178be3dfe1Sksagiyam PetscInt m, m1; 27188be3dfe1Sksagiyam 27199566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vec, &m1)); 27209566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(sectiondm, §ion)); 27219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints)); 27229566063dSJacob Faibussowitsch if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m)); 27239566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m)); 272463a3b9bcSJacob Faibussowitsch PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m); 27258be3dfe1Sksagiyam } 27269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 27279566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 27288be3dfe1Sksagiyam if (ishdf5) { 27298be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5) 27309566063dSJacob Faibussowitsch PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec)); 27318be3dfe1Sksagiyam #else 27328be3dfe1Sksagiyam SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 27338be3dfe1Sksagiyam #endif 27348be3dfe1Sksagiyam } 27359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0)); 27363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27378be3dfe1Sksagiyam } 27388be3dfe1Sksagiyam 2739d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm) 2740d71ae5a4SJacob Faibussowitsch { 2741552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 2742552f7358SJed Brown 2743552f7358SJed Brown PetscFunctionBegin; 27449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 27459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL)); 27469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL)); 27479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL)); 27486c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", NULL)); 27492e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 27502e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL)); 27512e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL)); 27522e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL)); 27536bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL)); 27546bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL)); 2755adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", NULL)); 2756adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", NULL)); 2757adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", NULL)); 2758adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", NULL)); 2759c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL)); 2760c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL)); 2761d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", NULL)); 2762d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", NULL)); 27635f06a3ddSJed Brown PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL)); 27643ba16761SJacob Faibussowitsch if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 27659566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->coneSection)); 27669566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->cones)); 27679566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->coneOrientations)); 27689566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->supportSection)); 27699566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->subdomainSection)); 27709566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->supports)); 277121027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 27729f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&mesh->tr)); 27739566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->tetgenOpts)); 27749566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->triangleOpts)); 27759566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->transformType)); 27761d1f2f2aSksagiyam PetscCall(PetscFree(mesh->distributionName)); 27779566063dSJacob Faibussowitsch PetscCall(PetscPartitionerDestroy(&mesh->partitioner)); 27789566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&mesh->subpointMap)); 27799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->subpointIS)); 27809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalVertexNumbers)); 27819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->globalCellNumbers)); 27821fca310dSJames Wright if (mesh->periodic.face_sfs) { 27831fca310dSJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(PetscSFDestroy(&mesh->periodic.face_sfs[i])); 27841fca310dSJames Wright PetscCall(PetscFree(mesh->periodic.face_sfs)); 27851fca310dSJames Wright } 27866725e60dSJed Brown PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf)); 2787b83f62b0SJames Wright if (mesh->periodic.periodic_points) { 2788b83f62b0SJames Wright for (PetscInt i = 0; i < mesh->periodic.num_face_sfs; i++) PetscCall(ISDestroy(&mesh->periodic.periodic_points[i])); 2789b83f62b0SJames Wright PetscCall(PetscFree(mesh->periodic.periodic_points)); 2790b83f62b0SJames Wright } 27911fca310dSJames Wright if (mesh->periodic.transform) PetscCall(PetscFree(mesh->periodic.transform)); 27929566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->anchorSection)); 27939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&mesh->anchorIS)); 27949566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->parentSection)); 27959566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->parents)); 27969566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->childIDs)); 27979566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&mesh->childSection)); 27989566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->children)); 27999566063dSJacob Faibussowitsch PetscCall(DMDestroy(&mesh->referenceTree)); 28009566063dSJacob Faibussowitsch PetscCall(PetscGridHashDestroy(&mesh->lbox)); 28019566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh->neighbors)); 28029566063dSJacob Faibussowitsch if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx)); 2803c29ce622SStefano Zampini if (mesh->nonempty_comm != MPI_COMM_NULL && mesh->nonempty_comm != MPI_COMM_SELF) PetscCallMPI(MPI_Comm_free(&mesh->nonempty_comm)); 2804552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 28059566063dSJacob Faibussowitsch PetscCall(PetscFree(mesh)); 28063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2807552f7358SJed Brown } 2808552f7358SJed Brown 2809d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 2810d71ae5a4SJacob Faibussowitsch { 2811d02c7345SMatthew G. Knepley PetscSection sectionGlobal, sectionLocal; 2812acd755d7SMatthew G. Knepley PetscInt bs = -1, mbs; 28139fca9976SJed Brown PetscInt localSize, localStart = 0; 2814837628f4SStefano Zampini PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS; 2815b412c318SBarry Smith MatType mtype; 28161428887cSShri Abhyankar ISLocalToGlobalMapping ltog; 2817552f7358SJed Brown 2818552f7358SJed Brown PetscFunctionBegin; 28199566063dSJacob Faibussowitsch PetscCall(MatInitializePackage()); 2820b412c318SBarry Smith mtype = dm->mattype; 2821d02c7345SMatthew G. Knepley PetscCall(DMGetLocalSection(dm, §ionLocal)); 28229566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 28239566063dSJacob Faibussowitsch /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */ 28249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize)); 28259fca9976SJed Brown PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 28269566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J)); 28279566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE)); 28289566063dSJacob Faibussowitsch PetscCall(MatSetType(*J, mtype)); 28299566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*J)); 28309566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(*J, &mbs)); 2831acd755d7SMatthew G. Knepley if (mbs > 1) bs = mbs; 28329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell)); 28339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock)); 28349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock)); 28359566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock)); 28369566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock)); 28379566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock)); 28389566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock)); 28399566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS)); 2840552f7358SJed Brown if (!isShell) { 28411c6742e7SMatthew G. Knepley // There are three states with pblocks, since block starts can have no dofs: 28421c6742e7SMatthew G. Knepley // UNKNOWN) New Block: An open block has been signalled by pblocks[p] == 1 28431c6742e7SMatthew G. Knepley // TRUE) Block Start: The first entry in a block has been added 28441c6742e7SMatthew G. Knepley // FALSE) Block Add: An additional block entry has been added, since pblocks[p] == 0 28451c6742e7SMatthew G. Knepley PetscBT blst; 28461c6742e7SMatthew G. Knepley PetscBool3 bstate = PETSC_BOOL3_UNKNOWN; 2847837628f4SStefano Zampini PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS); 28481c6742e7SMatthew G. Knepley const PetscInt *perm = NULL; 28499fca9976SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks; 28501c6742e7SMatthew G. Knepley PetscInt pStart, pEnd, dof, cdof, num_fields; 2851552f7358SJed Brown 28529566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(dm, <og)); 28531c6742e7SMatthew G. Knepley PetscCall(PetscSectionGetBlockStarts(sectionLocal, &blst)); 28541c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISGetIndices(sectionLocal->perm, &perm)); 28559fca9976SJed Brown 28569fca9976SJed Brown PetscCall(PetscCalloc1(localSize, &pblocks)); 28579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd)); 2858863027abSJed Brown PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields)); 28591c6742e7SMatthew G. Knepley // We need to process in the permuted order to get block sizes right 28601c6742e7SMatthew G. Knepley for (PetscInt point = pStart; point < pEnd; ++point) { 28611c6742e7SMatthew G. Knepley const PetscInt p = perm ? perm[point] : point; 28621c6742e7SMatthew G. Knepley 2863863027abSJed Brown switch (dm->blocking_type) { 28640e762ea3SJed Brown case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point 28659fca9976SJed Brown PetscInt bdof, offset; 2866a9d99c84SMatthew G. Knepley 28679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof)); 28689fca9976SJed Brown PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset)); 28699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof)); 28701c6742e7SMatthew G. Knepley if (blst && PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_UNKNOWN; 287132b27637SMatthew G. Knepley if (dof > 0) { 28721c6742e7SMatthew G. Knepley // State change 28731c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_UNKNOWN) bstate = PETSC_BOOL3_TRUE; 28741c6742e7SMatthew G. Knepley else if (bstate == PETSC_BOOL3_TRUE && blst && !PetscBTLookup(blst, p)) bstate = PETSC_BOOL3_FALSE; 28751c6742e7SMatthew G. Knepley 2876d02c7345SMatthew G. Knepley for (PetscInt i = 0; i < dof - cdof; ++i) pblocks[offset - localStart + i] = dof - cdof; 2877d02c7345SMatthew G. Knepley // Signal block concatenation 28781c6742e7SMatthew G. Knepley if (bstate == PETSC_BOOL3_FALSE && dof - cdof) pblocks[offset - localStart] = -(dof - cdof); 287932b27637SMatthew G. Knepley } 28801d17a0a3SMatthew G. Knepley dof = dof < 0 ? -(dof + 1) : dof; 28811d17a0a3SMatthew G. Knepley bdof = cdof && (dof - cdof) ? 1 : dof; 28821d17a0a3SMatthew G. Knepley if (dof) { 28839371c9d4SSatish Balay if (bs < 0) { 28849371c9d4SSatish Balay bs = bdof; 28859371c9d4SSatish Balay } else if (bs != bdof) { 28869371c9d4SSatish Balay bs = 1; 28879371c9d4SSatish Balay } 2888552f7358SJed Brown } 2889863027abSJed Brown } break; 2890863027abSJed Brown case DM_BLOCKING_FIELD_NODE: { 2891863027abSJed Brown for (PetscInt field = 0; field < num_fields; field++) { 2892863027abSJed Brown PetscInt num_comp, bdof, offset; 2893863027abSJed Brown PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp)); 2894863027abSJed Brown PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof)); 2895863027abSJed Brown if (dof < 0) continue; 2896863027abSJed Brown PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset)); 2897863027abSJed Brown PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof)); 2898863027abSJed 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); 2899863027abSJed Brown PetscInt num_nodes = dof / num_comp; 2900863027abSJed Brown for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes; 2901863027abSJed Brown // Handle possibly constant block size (unlikely) 2902863027abSJed Brown bdof = cdof && (dof - cdof) ? 1 : dof; 2903863027abSJed Brown if (dof) { 2904863027abSJed Brown if (bs < 0) { 2905863027abSJed Brown bs = bdof; 2906863027abSJed Brown } else if (bs != bdof) { 2907863027abSJed Brown bs = 1; 2908863027abSJed Brown } 2909863027abSJed Brown } 2910863027abSJed Brown } 2911863027abSJed Brown } break; 2912863027abSJed Brown } 29132a28c762SMatthew G Knepley } 29141c6742e7SMatthew G. Knepley if (sectionLocal->perm) PetscCall(ISRestoreIndices(sectionLocal->perm, &perm)); 29152a28c762SMatthew G Knepley /* Must have same blocksize on all procs (some might have no points) */ 2916e432b41dSStefano Zampini bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 2917e432b41dSStefano Zampini bsLocal[1] = bs; 29189566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 2919e432b41dSStefano Zampini if (bsMinMax[0] != bsMinMax[1]) bs = 1; 2920e432b41dSStefano Zampini else bs = bsMinMax[0]; 29216fd5c86aSStefano Zampini bs = PetscMax(1, bs); 29229566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog)); 29230682b8bbSJed Brown if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters 29249566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*J, bs)); 29259566063dSJacob Faibussowitsch PetscCall(MatSetUp(*J)); 29260682b8bbSJed Brown } else { 29279566063dSJacob Faibussowitsch PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu)); 29289566063dSJacob Faibussowitsch PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix)); 29299566063dSJacob Faibussowitsch PetscCall(PetscFree4(dnz, onz, dnzu, onzu)); 2930552f7358SJed Brown } 293132b27637SMatthew G. Knepley if (pblocks) { // Consolidate blocks 29329fca9976SJed Brown PetscInt nblocks = 0; 293332b27637SMatthew G. Knepley pblocks[0] = PetscAbs(pblocks[0]); 29349fca9976SJed Brown for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) { 29359fca9976SJed Brown if (pblocks[i] == 0) continue; 2936d02c7345SMatthew G. Knepley // Negative block size indicates the blocks should be concatenated 2937d02c7345SMatthew G. Knepley if (pblocks[i] < 0) { 2938d02c7345SMatthew G. Knepley pblocks[i] = -pblocks[i]; 2939d02c7345SMatthew G. Knepley pblocks[nblocks - 1] += pblocks[i]; 2940d02c7345SMatthew G. Knepley } else { 29419fca9976SJed Brown pblocks[nblocks++] = pblocks[i]; // nblocks always <= i 2942d02c7345SMatthew G. Knepley } 29431c6742e7SMatthew G. Knepley for (PetscInt j = 1; j < pblocks[i]; j++) 29441c6742e7SMatthew G. Knepley PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " at %" PetscInt_FMT " mismatches entry %" PetscInt_FMT " at %" PetscInt_FMT, pblocks[i], i, pblocks[i + j], i + j); 29459fca9976SJed Brown } 29469fca9976SJed Brown PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks)); 29479fca9976SJed Brown } 29489fca9976SJed Brown PetscCall(PetscFree(pblocks)); 2949aa0f6e3cSJed Brown } 29509566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm)); 29513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2952552f7358SJed Brown } 2953552f7358SJed Brown 29547cd05799SMatthew G. Knepley /*@ 2955a8f00d21SMatthew G. Knepley DMPlexGetSubdomainSection - Returns the section associated with the subdomain 2956be36d101SStefano Zampini 2957a1cb98faSBarry Smith Not Collective 2958be36d101SStefano Zampini 2959be36d101SStefano Zampini Input Parameter: 296060225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2961be36d101SStefano Zampini 29622fe279fdSBarry Smith Output Parameter: 2963be36d101SStefano Zampini . subsection - The subdomain section 2964be36d101SStefano Zampini 2965be36d101SStefano Zampini Level: developer 2966be36d101SStefano Zampini 29671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection` 29687cd05799SMatthew G. Knepley @*/ 2969d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) 2970d71ae5a4SJacob Faibussowitsch { 2971be36d101SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 2972be36d101SStefano Zampini 2973be36d101SStefano Zampini PetscFunctionBegin; 2974be36d101SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2975be36d101SStefano Zampini if (!mesh->subdomainSection) { 2976be36d101SStefano Zampini PetscSection section; 2977be36d101SStefano Zampini PetscSF sf; 2978be36d101SStefano Zampini 29799566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf)); 29809566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 2981eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection)); 29829566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 2983be36d101SStefano Zampini } 2984be36d101SStefano Zampini *subsection = mesh->subdomainSection; 29853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2986be36d101SStefano Zampini } 2987be36d101SStefano Zampini 2988552f7358SJed Brown /*@ 298920f4b53cSBarry Smith DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`) 2990552f7358SJed Brown 2991a1cb98faSBarry Smith Not Collective 2992552f7358SJed Brown 2993552f7358SJed Brown Input Parameter: 299460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 2995552f7358SJed Brown 2996552f7358SJed Brown Output Parameters: 2997552f7358SJed Brown + pStart - The first mesh point 2998552f7358SJed Brown - pEnd - The upper bound for mesh points 2999552f7358SJed Brown 3000552f7358SJed Brown Level: beginner 3001552f7358SJed Brown 30021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()` 3003552f7358SJed Brown @*/ 3004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 3005d71ae5a4SJacob Faibussowitsch { 3006552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3007552f7358SJed Brown 3008552f7358SJed Brown PetscFunctionBegin; 3009552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30109f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd)); 30119f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd)); 30123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3013552f7358SJed Brown } 3014552f7358SJed Brown 3015552f7358SJed Brown /*@ 301620f4b53cSBarry Smith DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`) 3017552f7358SJed Brown 3018a1cb98faSBarry Smith Not Collective 3019552f7358SJed Brown 3020552f7358SJed Brown Input Parameters: 302160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3022552f7358SJed Brown . pStart - The first mesh point 3023552f7358SJed Brown - pEnd - The upper bound for mesh points 3024552f7358SJed Brown 3025552f7358SJed Brown Level: beginner 3026552f7358SJed Brown 30271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()` 3028552f7358SJed Brown @*/ 3029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 3030d71ae5a4SJacob Faibussowitsch { 3031552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3032552f7358SJed Brown 3033552f7358SJed Brown PetscFunctionBegin; 3034552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd)); 30369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd)); 303721027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 30383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3039552f7358SJed Brown } 3040552f7358SJed Brown 3041552f7358SJed Brown /*@ 3042eaf898f9SPatrick Sanan DMPlexGetConeSize - Return the number of in-edges for this point in the DAG 3043552f7358SJed Brown 3044a1cb98faSBarry Smith Not Collective 3045552f7358SJed Brown 3046552f7358SJed Brown Input Parameters: 304760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3048a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3049552f7358SJed Brown 3050552f7358SJed Brown Output Parameter: 305120f4b53cSBarry Smith . size - The cone size for point `p` 3052552f7358SJed Brown 3053552f7358SJed Brown Level: beginner 3054552f7358SJed Brown 30551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 3056552f7358SJed Brown @*/ 3057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 3058d71ae5a4SJacob Faibussowitsch { 3059552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3060552f7358SJed Brown 3061552f7358SJed Brown PetscFunctionBegin; 3062552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30634f572ea9SToby Isaac PetscAssertPointer(size, 3); 30649f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size)); 30659f4ada15SMatthew G. Knepley else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size)); 30663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3067552f7358SJed Brown } 3068552f7358SJed Brown 3069552f7358SJed Brown /*@ 3070eaf898f9SPatrick Sanan DMPlexSetConeSize - Set the number of in-edges for this point in the DAG 3071552f7358SJed Brown 3072a1cb98faSBarry Smith Not Collective 3073552f7358SJed Brown 3074552f7358SJed Brown Input Parameters: 307560225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3076a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 307720f4b53cSBarry Smith - size - The cone size for point `p` 3078552f7358SJed Brown 3079552f7358SJed Brown Level: beginner 3080552f7358SJed Brown 3081a1cb98faSBarry Smith Note: 3082a1cb98faSBarry Smith This should be called after `DMPlexSetChart()`. 3083a1cb98faSBarry Smith 30842c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()` 3085552f7358SJed Brown @*/ 3086d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 3087d71ae5a4SJacob Faibussowitsch { 3088552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3089552f7358SJed Brown 3090552f7358SJed Brown PetscFunctionBegin; 3091552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30929f4ada15SMatthew G. Knepley PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined."); 30939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->coneSection, p, size)); 30943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3095552f7358SJed Brown } 3096552f7358SJed Brown 3097552f7358SJed Brown /*@C 3098eaf898f9SPatrick Sanan DMPlexGetCone - Return the points on the in-edges for this point in the DAG 3099552f7358SJed Brown 3100a1cb98faSBarry Smith Not Collective 3101552f7358SJed Brown 3102552f7358SJed Brown Input Parameters: 3103a1cb98faSBarry Smith + dm - The `DMPLEX` 3104a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3105552f7358SJed Brown 3106552f7358SJed Brown Output Parameter: 31072c9a7b26SBarry Smith . cone - An array of points which are on the in-edges for point `p`, the length of `cone` is the result of `DMPlexGetConeSize()` 3108552f7358SJed Brown 3109552f7358SJed Brown Level: beginner 3110552f7358SJed Brown 311160225df5SJacob Faibussowitsch Fortran Notes: 31122c9a7b26SBarry Smith `cone` must be declared with 31132c9a7b26SBarry Smith .vb 31142c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 31152c9a7b26SBarry Smith .ve 31162c9a7b26SBarry Smith 31172c9a7b26SBarry Smith You must also call `DMPlexRestoreCone()` after you finish using the array. 3118a1cb98faSBarry Smith `DMPlexRestoreCone()` is not needed/available in C. 31193813dfbdSMatthew G Knepley 31201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()` 3121552f7358SJed Brown @*/ 3122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 3123d71ae5a4SJacob Faibussowitsch { 3124552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3125552f7358SJed Brown PetscInt off; 3126552f7358SJed Brown 3127552f7358SJed Brown PetscFunctionBegin; 3128552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 31294f572ea9SToby Isaac PetscAssertPointer(cone, 3); 31309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 31318e3a54c0SPierre Jolivet *cone = PetscSafePointerPlusOffset(mesh->cones, off); 31323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3133552f7358SJed Brown } 3134552f7358SJed Brown 3135cc4c1da9SBarry Smith /*@ 31360ce7577fSVaclav Hapla DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG 31370ce7577fSVaclav Hapla 3138a1cb98faSBarry Smith Not Collective 31390ce7577fSVaclav Hapla 31400ce7577fSVaclav Hapla Input Parameters: 3141a1cb98faSBarry Smith + dm - The `DMPLEX` 3142a1cb98faSBarry Smith - p - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 31430ce7577fSVaclav Hapla 3144d8d19677SJose E. Roman Output Parameters: 314520f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones` 31462c9a7b26SBarry Smith - pCones - An `IS` containing the points which are on the in-edges for the point set `p` 31470ce7577fSVaclav Hapla 31480ce7577fSVaclav Hapla Level: intermediate 31490ce7577fSVaclav Hapla 31501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS` 31510ce7577fSVaclav Hapla @*/ 3152d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) 3153d71ae5a4SJacob Faibussowitsch { 31540ce7577fSVaclav Hapla PetscSection cs, newcs; 31550ce7577fSVaclav Hapla PetscInt *cones; 31560ce7577fSVaclav Hapla PetscInt *newarr = NULL; 31570ce7577fSVaclav Hapla PetscInt n; 31580ce7577fSVaclav Hapla 31590ce7577fSVaclav Hapla PetscFunctionBegin; 31609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 31619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &cs)); 31629566063dSJacob Faibussowitsch PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL)); 31630ce7577fSVaclav Hapla if (pConesSection) *pConesSection = newcs; 31640ce7577fSVaclav Hapla if (pCones) { 31659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newcs, &n)); 31669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones)); 31670ce7577fSVaclav Hapla } 31683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31690ce7577fSVaclav Hapla } 31700ce7577fSVaclav Hapla 3171af9eab45SVaclav Hapla /*@ 3172af9eab45SVaclav Hapla DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices. 3173d4636a37SVaclav Hapla 3174a1cb98faSBarry Smith Not Collective 3175d4636a37SVaclav Hapla 3176d4636a37SVaclav Hapla Input Parameters: 3177a1cb98faSBarry Smith + dm - The `DMPLEX` 3178a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3179d4636a37SVaclav Hapla 3180d4636a37SVaclav Hapla Output Parameter: 31812c9a7b26SBarry Smith . expandedPoints - An `IS` containing the of vertices recursively expanded from input points 3182d4636a37SVaclav Hapla 3183d4636a37SVaclav Hapla Level: advanced 3184d4636a37SVaclav Hapla 3185af9eab45SVaclav Hapla Notes: 318620f4b53cSBarry Smith Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections. 3187af9eab45SVaclav Hapla 3188a1cb98faSBarry Smith There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate. 3189a1cb98faSBarry Smith 31901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, 3191a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS` 3192d4636a37SVaclav Hapla @*/ 3193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) 3194d71ae5a4SJacob Faibussowitsch { 3195af9eab45SVaclav Hapla IS *expandedPointsAll; 3196af9eab45SVaclav Hapla PetscInt depth; 3197d4636a37SVaclav Hapla 3198d4636a37SVaclav Hapla PetscFunctionBegin; 3199af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3200af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 32014f572ea9SToby Isaac PetscAssertPointer(expandedPoints, 3); 32029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 3203af9eab45SVaclav Hapla *expandedPoints = expandedPointsAll[0]; 32049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0])); 32059566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL)); 32063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3207af9eab45SVaclav Hapla } 3208af9eab45SVaclav Hapla 3209af9eab45SVaclav Hapla /*@ 32102c9a7b26SBarry Smith DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices 32112c9a7b26SBarry Smith (DAG points of depth 0, i.e., without cones). 3212af9eab45SVaclav Hapla 3213a1cb98faSBarry Smith Not Collective 3214af9eab45SVaclav Hapla 3215af9eab45SVaclav Hapla Input Parameters: 3216a1cb98faSBarry Smith + dm - The `DMPLEX` 3217a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3218af9eab45SVaclav Hapla 3219d8d19677SJose E. Roman Output Parameters: 3220a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3221af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones 3222af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3223af9eab45SVaclav Hapla 3224af9eab45SVaclav Hapla Level: advanced 3225af9eab45SVaclav Hapla 3226af9eab45SVaclav Hapla Notes: 3227a1cb98faSBarry Smith Like `DMPlexGetConeTuple()` but recursive. 3228af9eab45SVaclav Hapla 3229a4e35b19SJacob 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. 3230af9eab45SVaclav Hapla For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc. 3231af9eab45SVaclav Hapla 3232a4e35b19SJacob 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\: 3233a4e35b19SJacob Faibussowitsch (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d]; 3234a4e35b19SJacob Faibussowitsch (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d]. 3235af9eab45SVaclav Hapla 32361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3237a1cb98faSBarry Smith `DMPlexGetDepth()`, `PetscSection`, `IS` 3238af9eab45SVaclav Hapla @*/ 3239d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3240d71ae5a4SJacob Faibussowitsch { 3241af9eab45SVaclav Hapla const PetscInt *arr0 = NULL, *cone = NULL; 3242af9eab45SVaclav Hapla PetscInt *arr = NULL, *newarr = NULL; 3243af9eab45SVaclav Hapla PetscInt d, depth_, i, n, newn, cn, co, start, end; 3244af9eab45SVaclav Hapla IS *expandedPoints_; 3245af9eab45SVaclav Hapla PetscSection *sections_; 3246af9eab45SVaclav Hapla 3247af9eab45SVaclav Hapla PetscFunctionBegin; 3248af9eab45SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3249af9eab45SVaclav Hapla PetscValidHeaderSpecific(points, IS_CLASSID, 2); 32504f572ea9SToby Isaac if (depth) PetscAssertPointer(depth, 3); 32514f572ea9SToby Isaac if (expandedPoints) PetscAssertPointer(expandedPoints, 4); 32524f572ea9SToby Isaac if (sections) PetscAssertPointer(sections, 5); 32539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(points, &n)); 32549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &arr0)); 32559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 32569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, &expandedPoints_)); 32579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(depth_, §ions_)); 3258af9eab45SVaclav Hapla arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */ 3259af9eab45SVaclav Hapla for (d = depth_ - 1; d >= 0; d--) { 32609566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, §ions_[d])); 32619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(sections_[d], 0, n)); 3262af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 32639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end)); 3264af9eab45SVaclav Hapla if (arr[i] >= start && arr[i] < end) { 32659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, arr[i], &cn)); 32669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, cn)); 3267af9eab45SVaclav Hapla } else { 32689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(sections_[d], i, 1)); 3269af9eab45SVaclav Hapla } 3270af9eab45SVaclav Hapla } 32719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(sections_[d])); 32729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(sections_[d], &newn)); 32739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newn, &newarr)); 3274af9eab45SVaclav Hapla for (i = 0; i < n; i++) { 32759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sections_[d], i, &cn)); 32769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sections_[d], i, &co)); 3277af9eab45SVaclav Hapla if (cn > 1) { 32789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, arr[i], &cone)); 32799566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt))); 3280af9eab45SVaclav Hapla } else { 3281af9eab45SVaclav Hapla newarr[co] = arr[i]; 3282af9eab45SVaclav Hapla } 3283af9eab45SVaclav Hapla } 32849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d])); 3285af9eab45SVaclav Hapla arr = newarr; 3286af9eab45SVaclav Hapla n = newn; 3287af9eab45SVaclav Hapla } 32889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &arr0)); 3289af9eab45SVaclav Hapla *depth = depth_; 3290af9eab45SVaclav Hapla if (expandedPoints) *expandedPoints = expandedPoints_; 3291af9eab45SVaclav Hapla else { 32929566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d])); 32939566063dSJacob Faibussowitsch PetscCall(PetscFree(expandedPoints_)); 3294af9eab45SVaclav Hapla } 3295af9eab45SVaclav Hapla if (sections) *sections = sections_; 3296af9eab45SVaclav Hapla else { 32979566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(§ions_[d])); 32989566063dSJacob Faibussowitsch PetscCall(PetscFree(sections_)); 3299af9eab45SVaclav Hapla } 33003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3301af9eab45SVaclav Hapla } 3302af9eab45SVaclav Hapla 3303af9eab45SVaclav Hapla /*@ 3304a1cb98faSBarry Smith DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()` 3305af9eab45SVaclav Hapla 3306a1cb98faSBarry Smith Not Collective 3307af9eab45SVaclav Hapla 3308af9eab45SVaclav Hapla Input Parameters: 3309a1cb98faSBarry Smith + dm - The `DMPLEX` 3310a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()` 3311af9eab45SVaclav Hapla 3312d8d19677SJose E. Roman Output Parameters: 3313a1cb98faSBarry Smith + depth - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()` 3314af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones 3315af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points 3316af9eab45SVaclav Hapla 3317af9eab45SVaclav Hapla Level: advanced 3318af9eab45SVaclav Hapla 3319a1cb98faSBarry Smith Note: 3320a1cb98faSBarry Smith See `DMPlexGetConeRecursive()` 3321af9eab45SVaclav Hapla 33221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, 3323a1cb98faSBarry Smith `DMPlexGetDepth()`, `IS`, `PetscSection` 3324af9eab45SVaclav Hapla @*/ 3325d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) 3326d71ae5a4SJacob Faibussowitsch { 3327af9eab45SVaclav Hapla PetscInt d, depth_; 3328af9eab45SVaclav Hapla 3329af9eab45SVaclav Hapla PetscFunctionBegin; 33309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth_)); 33311dca8a05SBarry Smith PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive"); 3332af9eab45SVaclav Hapla if (depth) *depth = 0; 3333af9eab45SVaclav Hapla if (expandedPoints) { 33349566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d]))); 33359566063dSJacob Faibussowitsch PetscCall(PetscFree(*expandedPoints)); 3336af9eab45SVaclav Hapla } 3337af9eab45SVaclav Hapla if (sections) { 33389566063dSJacob Faibussowitsch for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d]))); 33399566063dSJacob Faibussowitsch PetscCall(PetscFree(*sections)); 3340af9eab45SVaclav Hapla } 33413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3342d4636a37SVaclav Hapla } 3343d4636a37SVaclav Hapla 3344552f7358SJed Brown /*@ 334592371b87SBarry 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 3346552f7358SJed Brown 3347a1cb98faSBarry Smith Not Collective 3348552f7358SJed Brown 3349552f7358SJed Brown Input Parameters: 335060225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3351a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 33522c9a7b26SBarry Smith - cone - An array of points which are on the in-edges for point `p`, its length must have been previously provided with `DMPlexSetConeSize()` 3353552f7358SJed Brown 3354552f7358SJed Brown Level: beginner 3355552f7358SJed Brown 3356a1cb98faSBarry Smith Note: 3357a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3358a1cb98faSBarry Smith 33591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()` 3360552f7358SJed Brown @*/ 3361d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 3362d71ae5a4SJacob Faibussowitsch { 3363552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3364552f7358SJed Brown PetscInt dof, off, c; 3365552f7358SJed Brown 3366552f7358SJed Brown PetscFunctionBegin; 3367552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 33689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 33694f572ea9SToby Isaac if (dof) PetscAssertPointer(cone, 3); 33709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3371db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3372db485b19SStefano Zampini PetscInt pStart, pEnd; 3373db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 337463a3b9bcSJacob 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); 3375552f7358SJed Brown for (c = 0; c < dof; ++c) { 337663a3b9bcSJacob 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); 3377552f7358SJed Brown mesh->cones[off + c] = cone[c]; 3378552f7358SJed Brown } 3379db485b19SStefano Zampini } else { 3380db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c]; 3381db485b19SStefano Zampini } 33823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3383552f7358SJed Brown } 3384552f7358SJed Brown 3385552f7358SJed Brown /*@C 3386eaf898f9SPatrick Sanan DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG 3387552f7358SJed Brown 3388a1cb98faSBarry Smith Not Collective 3389552f7358SJed Brown 3390552f7358SJed Brown Input Parameters: 339160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3392a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3393552f7358SJed Brown 3394552f7358SJed Brown Output Parameter: 339520f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an 33962c9a7b26SBarry Smith integer giving the prescription for cone traversal. Its length is given by the result of `DMPlexSetConeSize()` 3397552f7358SJed Brown 3398552f7358SJed Brown Level: beginner 3399552f7358SJed Brown 3400a1cb98faSBarry Smith Note: 3401b5a892a1SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 3402b5a892a1SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 3403a1cb98faSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 3404b5a892a1SMatthew G. Knepley with the identity. 3405b5a892a1SMatthew G. Knepley 340660225df5SJacob Faibussowitsch Fortran Notes: 34072c9a7b26SBarry Smith You must call `DMPlexRestoreConeOrientation()` after you finish using the returned array. 3408a1cb98faSBarry Smith `DMPlexRestoreConeOrientation()` is not needed/available in C. 34093813dfbdSMatthew G Knepley 34102c9a7b26SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetConeSize()`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, 34112c9a7b26SBarry Smith `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()` 3412552f7358SJed Brown @*/ 3413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 3414d71ae5a4SJacob Faibussowitsch { 3415552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3416552f7358SJed Brown PetscInt off; 3417552f7358SJed Brown 3418552f7358SJed Brown PetscFunctionBegin; 3419552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 342076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3421552f7358SJed Brown PetscInt dof; 34229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34234f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 3424552f7358SJed Brown } 34259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 34260d644c17SKarl Rupp 3427552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 34283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3429552f7358SJed Brown } 3430552f7358SJed Brown 3431552f7358SJed Brown /*@ 3432eaf898f9SPatrick Sanan DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG 3433552f7358SJed Brown 3434a1cb98faSBarry Smith Not Collective 3435552f7358SJed Brown 3436552f7358SJed Brown Input Parameters: 343760225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3438a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34392c9a7b26SBarry Smith - coneOrientation - An array of orientations. Its length is given by the result of `DMPlexSetConeSize()` 3440b5a892a1SMatthew G. Knepley 3441552f7358SJed Brown Level: beginner 3442552f7358SJed Brown 3443a1cb98faSBarry Smith Notes: 3444a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`. 3445a1cb98faSBarry Smith 3446a1cb98faSBarry Smith The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`. 3447a1cb98faSBarry Smith 34481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 3449552f7358SJed Brown @*/ 3450d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 3451d71ae5a4SJacob Faibussowitsch { 3452552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3453552f7358SJed Brown PetscInt pStart, pEnd; 3454552f7358SJed Brown PetscInt dof, off, c; 3455552f7358SJed Brown 3456552f7358SJed Brown PetscFunctionBegin; 3457552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 34589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 34594f572ea9SToby Isaac if (dof) PetscAssertPointer(coneOrientation, 3); 34609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3461db485b19SStefano Zampini if (PetscDefined(USE_DEBUG)) { 3462db485b19SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 346363a3b9bcSJacob 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); 3464552f7358SJed Brown for (c = 0; c < dof; ++c) { 3465552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 3466552f7358SJed Brown 34679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof)); 34681dca8a05SBarry 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); 3469552f7358SJed Brown mesh->coneOrientations[off + c] = o; 3470552f7358SJed Brown } 3471db485b19SStefano Zampini } else { 3472db485b19SStefano Zampini for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c]; 3473db485b19SStefano Zampini } 34743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3475552f7358SJed Brown } 3476552f7358SJed Brown 34777cd05799SMatthew G. Knepley /*@ 3478eaf898f9SPatrick Sanan DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG 34797cd05799SMatthew G. Knepley 3480a1cb98faSBarry Smith Not Collective 34817cd05799SMatthew G. Knepley 34827cd05799SMatthew G. Knepley Input Parameters: 348360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3484a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 34857cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 34867cd05799SMatthew G. Knepley - conePoint - The mesh point to insert 34877cd05799SMatthew G. Knepley 34887cd05799SMatthew G. Knepley Level: beginner 34897cd05799SMatthew G. Knepley 34901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 34917cd05799SMatthew G. Knepley @*/ 3492d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 3493d71ae5a4SJacob Faibussowitsch { 3494552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3495552f7358SJed Brown PetscInt pStart, pEnd; 3496552f7358SJed Brown PetscInt dof, off; 3497552f7358SJed Brown 3498552f7358SJed Brown PetscFunctionBegin; 3499552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3500a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 35019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 350263a3b9bcSJacob 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); 350363a3b9bcSJacob 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); 35049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 350563a3b9bcSJacob 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); 3506a03d55ffSStefano Zampini } 3507a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 3508552f7358SJed Brown mesh->cones[off + conePos] = conePoint; 35093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3510552f7358SJed Brown } 3511552f7358SJed Brown 35127cd05799SMatthew G. Knepley /*@ 3513eaf898f9SPatrick Sanan DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG 35147cd05799SMatthew G. Knepley 3515a1cb98faSBarry Smith Not Collective 35167cd05799SMatthew G. Knepley 35177cd05799SMatthew G. Knepley Input Parameters: 351860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3519a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 35207cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put 35217cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert 35227cd05799SMatthew G. Knepley 35237cd05799SMatthew G. Knepley Level: beginner 35247cd05799SMatthew G. Knepley 3525a1cb98faSBarry Smith Note: 3526a1cb98faSBarry Smith The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`. 3527b5a892a1SMatthew G. Knepley 35281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 35297cd05799SMatthew G. Knepley @*/ 3530d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 3531d71ae5a4SJacob Faibussowitsch { 353277c88f5bSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 353377c88f5bSMatthew G Knepley PetscInt pStart, pEnd; 353477c88f5bSMatthew G Knepley PetscInt dof, off; 353577c88f5bSMatthew G Knepley 353677c88f5bSMatthew G Knepley PetscFunctionBegin; 353777c88f5bSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3538a03d55ffSStefano Zampini if (PetscDefined(USE_DEBUG)) { 35399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 354063a3b9bcSJacob 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); 35419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 354263a3b9bcSJacob 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); 3543a03d55ffSStefano Zampini } 3544a03d55ffSStefano Zampini PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 354577c88f5bSMatthew G Knepley mesh->coneOrientations[off + conePos] = coneOrientation; 35463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 354777c88f5bSMatthew G Knepley } 354877c88f5bSMatthew G Knepley 35499f4ada15SMatthew G. Knepley /*@C 35509f4ada15SMatthew G. Knepley DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG 35519f4ada15SMatthew G. Knepley 35529f4ada15SMatthew G. Knepley Not collective 35539f4ada15SMatthew G. Knepley 35549f4ada15SMatthew G. Knepley Input Parameters: 35559f4ada15SMatthew G. Knepley + dm - The DMPlex 35569f4ada15SMatthew G. Knepley - p - The point, which must lie in the chart set with DMPlexSetChart() 35579f4ada15SMatthew G. Knepley 35589f4ada15SMatthew G. Knepley Output Parameters: 355920f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p` 356020f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 35619f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 35629f4ada15SMatthew G. Knepley 35639f4ada15SMatthew G. Knepley Level: beginner 35649f4ada15SMatthew G. Knepley 35659f4ada15SMatthew G. Knepley Notes: 35669f4ada15SMatthew G. Knepley The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always 35679f4ada15SMatthew G. Knepley the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection 356820f4b53cSBarry Smith of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()` 35699f4ada15SMatthew G. Knepley with the identity. 35709f4ada15SMatthew G. Knepley 35712c9a7b26SBarry Smith You must also call `DMPlexRestoreOrientedCone()` after you finish using the returned array. 35722c9a7b26SBarry Smith 35739f4ada15SMatthew G. Knepley Fortran Notes: 35742c9a7b26SBarry Smith `cone` and `ornt` must be declared with 35752c9a7b26SBarry Smith .vb 35762c9a7b26SBarry Smith PetscInt, pointer :: cone(:) 35772c9a7b26SBarry Smith PetscInt, pointer :: ornt(:) 35782c9a7b26SBarry Smith .ve 35799f4ada15SMatthew G. Knepley 35801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 35819f4ada15SMatthew G. Knepley @*/ 35829f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 35839f4ada15SMatthew G. Knepley { 35849f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 35859f4ada15SMatthew G. Knepley 35869f4ada15SMatthew G. Knepley PetscFunctionBegin; 35879f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 35889f4ada15SMatthew G. Knepley if (mesh->tr) { 35899f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt)); 35909f4ada15SMatthew G. Knepley } else { 35919f4ada15SMatthew G. Knepley PetscInt off; 35929f4ada15SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 35939f4ada15SMatthew G. Knepley PetscInt dof; 35949f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 35959f4ada15SMatthew G. Knepley if (dof) { 35964f572ea9SToby Isaac if (cone) PetscAssertPointer(cone, 3); 35974f572ea9SToby Isaac if (ornt) PetscAssertPointer(ornt, 4); 35989f4ada15SMatthew G. Knepley } 35999f4ada15SMatthew G. Knepley } 36009f4ada15SMatthew G. Knepley PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 36018e3a54c0SPierre Jolivet if (cone) *cone = PetscSafePointerPlusOffset(mesh->cones, off); 36028e3a54c0SPierre Jolivet if (ornt) *ornt = PetscSafePointerPlusOffset(mesh->coneOrientations, off); 36039f4ada15SMatthew G. Knepley } 36043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36059f4ada15SMatthew G. Knepley } 36069f4ada15SMatthew G. Knepley 36079f4ada15SMatthew G. Knepley /*@C 36082c9a7b26SBarry Smith DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG obtained with `DMPlexGetOrientedCone()` 36099f4ada15SMatthew G. Knepley 361020f4b53cSBarry Smith Not Collective 36119f4ada15SMatthew G. Knepley 36129f4ada15SMatthew G. Knepley Input Parameters: 36139f4ada15SMatthew G. Knepley + dm - The DMPlex 361420f4b53cSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 36159f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p 361620f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an 36179f4ada15SMatthew G. Knepley integer giving the prescription for cone traversal. 36189f4ada15SMatthew G. Knepley 36199f4ada15SMatthew G. Knepley Level: beginner 36209f4ada15SMatthew G. Knepley 36211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()` 36229f4ada15SMatthew G. Knepley @*/ 36239f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[]) 36249f4ada15SMatthew G. Knepley { 36259f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 36269f4ada15SMatthew G. Knepley 36279f4ada15SMatthew G. Knepley PetscFunctionBegin; 36289f4ada15SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36299f4ada15SMatthew G. Knepley if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt)); 36303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36319f4ada15SMatthew G. Knepley } 36329f4ada15SMatthew G. Knepley 3633552f7358SJed Brown /*@ 3634eaf898f9SPatrick Sanan DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG 3635552f7358SJed Brown 3636a1cb98faSBarry Smith Not Collective 3637552f7358SJed Brown 3638552f7358SJed Brown Input Parameters: 363960225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3640a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3641552f7358SJed Brown 3642552f7358SJed Brown Output Parameter: 364320f4b53cSBarry Smith . size - The support size for point `p` 3644552f7358SJed Brown 3645552f7358SJed Brown Level: beginner 3646552f7358SJed Brown 36471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()` 3648552f7358SJed Brown @*/ 3649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 3650d71ae5a4SJacob Faibussowitsch { 3651552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3652552f7358SJed Brown 3653552f7358SJed Brown PetscFunctionBegin; 3654552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36554f572ea9SToby Isaac PetscAssertPointer(size, 3); 36569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, size)); 36573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3658552f7358SJed Brown } 3659552f7358SJed Brown 3660552f7358SJed Brown /*@ 3661eaf898f9SPatrick Sanan DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG 3662552f7358SJed Brown 3663a1cb98faSBarry Smith Not Collective 3664552f7358SJed Brown 3665552f7358SJed Brown Input Parameters: 366660225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3667a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 366820f4b53cSBarry Smith - size - The support size for point `p` 3669552f7358SJed Brown 3670a1cb98faSBarry Smith Level: beginner 3671552f7358SJed Brown 3672552f7358SJed Brown Note: 367320f4b53cSBarry Smith This should be called after `DMPlexSetChart()`. 3674552f7358SJed Brown 36751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()` 3676552f7358SJed Brown @*/ 3677d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 3678d71ae5a4SJacob Faibussowitsch { 3679552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3680552f7358SJed Brown 3681552f7358SJed Brown PetscFunctionBegin; 3682552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(mesh->supportSection, p, size)); 36843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3685552f7358SJed Brown } 3686552f7358SJed Brown 3687552f7358SJed Brown /*@C 3688eaf898f9SPatrick Sanan DMPlexGetSupport - Return the points on the out-edges for this point in the DAG 3689552f7358SJed Brown 3690a1cb98faSBarry Smith Not Collective 3691552f7358SJed Brown 3692552f7358SJed Brown Input Parameters: 369360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3694a1cb98faSBarry Smith - p - The point, which must lie in the chart set with `DMPlexSetChart()` 3695552f7358SJed Brown 3696552f7358SJed Brown Output Parameter: 36972c9a7b26SBarry Smith . support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3698552f7358SJed Brown 3699552f7358SJed Brown Level: beginner 3700552f7358SJed Brown 370160225df5SJacob Faibussowitsch Fortran Notes: 37022c9a7b26SBarry Smith `support` must be declared with 37032c9a7b26SBarry Smith .vb 37042c9a7b26SBarry Smith PetscInt, pointer :: support(:) 37052c9a7b26SBarry Smith .ve 37062c9a7b26SBarry Smith 3707a1cb98faSBarry Smith You must also call `DMPlexRestoreSupport()` after you finish using the returned array. 3708a1cb98faSBarry Smith `DMPlexRestoreSupport()` is not needed/available in C. 37093813dfbdSMatthew G Knepley 37101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()` 3711552f7358SJed Brown @*/ 3712d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 3713d71ae5a4SJacob Faibussowitsch { 3714552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3715552f7358SJed Brown PetscInt off; 3716552f7358SJed Brown 3717552f7358SJed Brown PetscFunctionBegin; 3718552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37194f572ea9SToby Isaac PetscAssertPointer(support, 3); 37209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 37218e3a54c0SPierre Jolivet *support = PetscSafePointerPlusOffset(mesh->supports, off); 37223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3723552f7358SJed Brown } 3724552f7358SJed Brown 3725552f7358SJed Brown /*@ 372692371b87SBarry 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 3727552f7358SJed Brown 3728a1cb98faSBarry Smith Not Collective 3729552f7358SJed Brown 3730552f7358SJed Brown Input Parameters: 373160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3732a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 37332c9a7b26SBarry Smith - support - An array of points which are on the out-edges for point `p`, its length is that obtained from `DMPlexGetSupportSize()` 3734552f7358SJed Brown 3735552f7358SJed Brown Level: beginner 3736552f7358SJed Brown 3737a1cb98faSBarry Smith Note: 3738a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`. 3739a1cb98faSBarry Smith 37401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()` 3741552f7358SJed Brown @*/ 3742d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 3743d71ae5a4SJacob Faibussowitsch { 3744552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3745552f7358SJed Brown PetscInt pStart, pEnd; 3746552f7358SJed Brown PetscInt dof, off, c; 3747552f7358SJed Brown 3748552f7358SJed Brown PetscFunctionBegin; 3749552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 37519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37524f572ea9SToby Isaac if (dof) PetscAssertPointer(support, 3); 37539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 375463a3b9bcSJacob 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); 3755552f7358SJed Brown for (c = 0; c < dof; ++c) { 375663a3b9bcSJacob 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); 3757552f7358SJed Brown mesh->supports[off + c] = support[c]; 3758552f7358SJed Brown } 37593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3760552f7358SJed Brown } 3761552f7358SJed Brown 37627cd05799SMatthew G. Knepley /*@ 3763eaf898f9SPatrick Sanan DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG 37647cd05799SMatthew G. Knepley 3765a1cb98faSBarry Smith Not Collective 37667cd05799SMatthew G. Knepley 37677cd05799SMatthew G. Knepley Input Parameters: 376860225df5SJacob Faibussowitsch + dm - The `DMPLEX` 3769a1cb98faSBarry Smith . p - The point, which must lie in the chart set with `DMPlexSetChart()` 37707cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put 37717cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert 37727cd05799SMatthew G. Knepley 37737cd05799SMatthew G. Knepley Level: beginner 37747cd05799SMatthew G. Knepley 37751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()` 37767cd05799SMatthew G. Knepley @*/ 3777d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 3778d71ae5a4SJacob Faibussowitsch { 3779552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 3780552f7358SJed Brown PetscInt pStart, pEnd; 3781552f7358SJed Brown PetscInt dof, off; 3782552f7358SJed Brown 3783552f7358SJed Brown PetscFunctionBegin; 3784552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 37859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd)); 37869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof)); 37879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off)); 378863a3b9bcSJacob 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); 378963a3b9bcSJacob 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); 379063a3b9bcSJacob 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); 3791552f7358SJed Brown mesh->supports[off + supportPos] = supportPoint; 37923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3793552f7358SJed Brown } 3794552f7358SJed Brown 3795b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */ 3796d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) 3797d71ae5a4SJacob Faibussowitsch { 3798b5a892a1SMatthew G. Knepley switch (ct) { 3799b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3800b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3801b5a892a1SMatthew G. Knepley break; 3802b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3803b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3804b5a892a1SMatthew G. Knepley if (o == -2) return -3; 3805b5a892a1SMatthew G. Knepley if (o == -1) return -2; 3806b5a892a1SMatthew G. Knepley break; 3807b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3808b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3809b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3810b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3811b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3812b5a892a1SMatthew G. Knepley break; 3813d71ae5a4SJacob Faibussowitsch default: 3814d71ae5a4SJacob Faibussowitsch return o; 3815b5a892a1SMatthew G. Knepley } 3816b5a892a1SMatthew G. Knepley return o; 3817b5a892a1SMatthew G. Knepley } 3818b5a892a1SMatthew G. Knepley 3819b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */ 3820d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) 3821d71ae5a4SJacob Faibussowitsch { 3822b5a892a1SMatthew G. Knepley switch (ct) { 3823b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 3824b5a892a1SMatthew G. Knepley if ((o == -2) || (o == 1)) return -1; 3825b5a892a1SMatthew G. Knepley if (o == -1) return 0; 3826b5a892a1SMatthew G. Knepley break; 3827b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 3828b5a892a1SMatthew G. Knepley if (o == -3) return -2; 3829b5a892a1SMatthew G. Knepley if (o == -2) return -1; 3830b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3831b5a892a1SMatthew G. Knepley break; 3832b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 3833b5a892a1SMatthew G. Knepley if (o == -4) return -2; 3834b5a892a1SMatthew G. Knepley if (o == -3) return -1; 3835b5a892a1SMatthew G. Knepley if (o == -2) return -4; 3836b5a892a1SMatthew G. Knepley if (o == -1) return -3; 3837b5a892a1SMatthew G. Knepley break; 3838d71ae5a4SJacob Faibussowitsch default: 3839d71ae5a4SJacob Faibussowitsch return o; 3840b5a892a1SMatthew G. Knepley } 3841b5a892a1SMatthew G. Knepley return o; 3842b5a892a1SMatthew G. Knepley } 3843b5a892a1SMatthew G. Knepley 3844b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */ 3845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) 3846d71ae5a4SJacob Faibussowitsch { 3847b5a892a1SMatthew G. Knepley PetscInt pStart, pEnd, p; 3848b5a892a1SMatthew G. Knepley 3849b5a892a1SMatthew G. Knepley PetscFunctionBegin; 38509566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 3851b5a892a1SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 3852b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3853b5a892a1SMatthew G. Knepley PetscInt coneSize, c; 3854b5a892a1SMatthew G. Knepley 38559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 38569566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 38579566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 3858b5a892a1SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 3859b5a892a1SMatthew G. Knepley DMPolytopeType ct; 3860b5a892a1SMatthew G. Knepley const PetscInt o = ornt[c]; 3861b5a892a1SMatthew G. Knepley 38629566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[c], &ct)); 3863b5a892a1SMatthew G. Knepley switch (ct) { 3864b5a892a1SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 38659566063dSJacob Faibussowitsch if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 38669566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0)); 3867b5a892a1SMatthew G. Knepley break; 3868b5a892a1SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 38699566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 38709566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 38719566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3872b5a892a1SMatthew G. Knepley break; 3873b5a892a1SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 38749566063dSJacob Faibussowitsch if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2)); 38759566063dSJacob Faibussowitsch if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1)); 38769566063dSJacob Faibussowitsch if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4)); 38779566063dSJacob Faibussowitsch if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3)); 3878b5a892a1SMatthew G. Knepley break; 3879d71ae5a4SJacob Faibussowitsch default: 3880d71ae5a4SJacob Faibussowitsch break; 3881b5a892a1SMatthew G. Knepley } 3882b5a892a1SMatthew G. Knepley } 3883b5a892a1SMatthew G. Knepley } 38843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3885b5a892a1SMatthew G. Knepley } 3886b5a892a1SMatthew G. Knepley 388709015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 388809015e70SStefano Zampini { 388909015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 389009015e70SStefano Zampini 389109015e70SStefano Zampini PetscFunctionBeginHot; 389209015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 389309015e70SStefano Zampini if (useCone) { 389409015e70SStefano Zampini PetscCall(DMPlexGetConeSize(dm, p, size)); 389509015e70SStefano Zampini PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt)); 389609015e70SStefano Zampini } else { 389709015e70SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, p, size)); 389809015e70SStefano Zampini PetscCall(DMPlexGetSupport(dm, p, arr)); 389909015e70SStefano Zampini } 390009015e70SStefano Zampini } else { 390109015e70SStefano Zampini if (useCone) { 390209015e70SStefano Zampini const PetscSection s = mesh->coneSection; 390309015e70SStefano Zampini const PetscInt ps = p - s->pStart; 390409015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 390509015e70SStefano Zampini 390609015e70SStefano Zampini *size = s->atlasDof[ps]; 390709015e70SStefano Zampini *arr = mesh->cones + off; 390809015e70SStefano Zampini *ornt = mesh->coneOrientations + off; 390909015e70SStefano Zampini } else { 391009015e70SStefano Zampini const PetscSection s = mesh->supportSection; 391109015e70SStefano Zampini const PetscInt ps = p - s->pStart; 391209015e70SStefano Zampini const PetscInt off = s->atlasOff[ps]; 391309015e70SStefano Zampini 391409015e70SStefano Zampini *size = s->atlasDof[ps]; 391509015e70SStefano Zampini *arr = mesh->supports + off; 391609015e70SStefano Zampini } 391709015e70SStefano Zampini } 391809015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 391909015e70SStefano Zampini } 392009015e70SStefano Zampini 392109015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[]) 392209015e70SStefano Zampini { 392309015e70SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 392409015e70SStefano Zampini 392509015e70SStefano Zampini PetscFunctionBeginHot; 392609015e70SStefano Zampini if (PetscDefined(USE_DEBUG) || mesh->tr) { 392709015e70SStefano Zampini if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt)); 392809015e70SStefano Zampini } 392909015e70SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 393009015e70SStefano Zampini } 393109015e70SStefano Zampini 3932d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 3933d71ae5a4SJacob Faibussowitsch { 3934b5a892a1SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 3935b5a892a1SMatthew G. Knepley PetscInt *closure; 3936b5a892a1SMatthew G. Knepley const PetscInt *tmp = NULL, *tmpO = NULL; 3937b5a892a1SMatthew G. Knepley PetscInt off = 0, tmpSize, t; 3938b5a892a1SMatthew G. Knepley 3939b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 3940b5a892a1SMatthew G. Knepley if (ornt) { 39419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 3942476787b7SMatthew 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; 3943b5a892a1SMatthew G. Knepley } 3944b5a892a1SMatthew G. Knepley if (*points) { 3945b5a892a1SMatthew G. Knepley closure = *points; 3946b5a892a1SMatthew G. Knepley } else { 3947b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize; 39489566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 39499566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure)); 3950b5a892a1SMatthew G. Knepley } 395109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3952b5a892a1SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) { 3953b5a892a1SMatthew G. Knepley closure[off++] = p; 3954b5a892a1SMatthew G. Knepley closure[off++] = 0; 3955b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3956b5a892a1SMatthew G. Knepley closure[off++] = tmp[t]; 3957b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? tmpO[t] : 0; 3958b5a892a1SMatthew G. Knepley } 3959b5a892a1SMatthew G. Knepley } else { 396085036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, ornt); 3961b5a892a1SMatthew G. Knepley 3962b5a892a1SMatthew G. Knepley /* We assume that cells with a valid type have faces with a valid type */ 3963b5a892a1SMatthew G. Knepley closure[off++] = p; 3964b5a892a1SMatthew G. Knepley closure[off++] = ornt; 3965b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 3966b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3967b5a892a1SMatthew G. Knepley 39689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, tmp[t], &ft)); 3969b5a892a1SMatthew G. Knepley closure[off++] = tmp[arr[t]]; 3970b5a892a1SMatthew G. Knepley closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0; 3971b5a892a1SMatthew G. Knepley } 3972b5a892a1SMatthew G. Knepley } 397309015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO)); 3974b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = tmpSize + 1; 3975b5a892a1SMatthew G. Knepley if (points) *points = closure; 39763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3977b5a892a1SMatthew G. Knepley } 3978b5a892a1SMatthew G. Knepley 3979d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */ 3980d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) 3981d71ae5a4SJacob Faibussowitsch { 398285036b15SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangement(ct, o); 3983b5a892a1SMatthew G. Knepley const PetscInt *cone, *ornt; 3984b5a892a1SMatthew G. Knepley PetscInt *pts, *closure = NULL; 3985b5a892a1SMatthew G. Knepley DMPolytopeType ft; 3986b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize; 3987b5a892a1SMatthew G. Knepley PetscInt dim, coneSize, c, d, clSize, cl; 3988b5a892a1SMatthew G. Knepley 3989b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 39909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 399109015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 39929566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 3993b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1; 3994b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1; 3995b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 39969371c9d4SSatish Balay if (*points) { 39979371c9d4SSatish Balay pts = *points; 39989371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts)); 3999b5a892a1SMatthew G. Knepley c = 0; 4000b5a892a1SMatthew G. Knepley pts[c++] = point; 4001b5a892a1SMatthew G. Knepley pts[c++] = o; 40029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft)); 40039566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure)); 40049371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40059371c9d4SSatish Balay pts[c++] = closure[cl]; 40069371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40079371c9d4SSatish Balay } 40089566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure)); 40099371c9d4SSatish Balay for (cl = 0; cl < clSize * 2; cl += 2) { 40109371c9d4SSatish Balay pts[c++] = closure[cl]; 40119371c9d4SSatish Balay pts[c++] = closure[cl + 1]; 40129371c9d4SSatish Balay } 40139566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure)); 4014b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 40159566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft)); 4016b5a892a1SMatthew G. Knepley pts[c++] = cone[arr[d * 2 + 0]]; 4017b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]); 4018b5a892a1SMatthew G. Knepley } 401909015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt)); 4020b5a892a1SMatthew G. Knepley if (dim >= 3) { 4021b5a892a1SMatthew G. Knepley for (d = 2; d < coneSize; ++d) { 4022b5a892a1SMatthew G. Knepley const PetscInt fpoint = cone[arr[d * 2 + 0]]; 4023b5a892a1SMatthew G. Knepley const PetscInt *fcone, *fornt; 4024b5a892a1SMatthew G. Knepley PetscInt fconeSize, fc, i; 4025b5a892a1SMatthew G. Knepley 40269566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, fpoint, &ft)); 402785036b15SMatthew G. Knepley const PetscInt *farr = DMPolytopeTypeGetArrangement(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d])); 402809015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4029b5a892a1SMatthew G. Knepley for (fc = 0; fc < fconeSize; ++fc) { 4030b5a892a1SMatthew G. Knepley const PetscInt cp = fcone[farr[fc * 2 + 0]]; 4031b5a892a1SMatthew G. Knepley const PetscInt co = farr[fc * 2 + 1]; 4032b5a892a1SMatthew G. Knepley 40339371c9d4SSatish Balay for (i = 0; i < c; i += 2) 40349371c9d4SSatish Balay if (pts[i] == cp) break; 4035b5a892a1SMatthew G. Knepley if (i == c) { 40369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ft)); 4037b5a892a1SMatthew G. Knepley pts[c++] = cp; 4038b5a892a1SMatthew G. Knepley pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]); 4039b5a892a1SMatthew G. Knepley } 4040b5a892a1SMatthew G. Knepley } 404109015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt)); 4042b5a892a1SMatthew G. Knepley } 4043b5a892a1SMatthew G. Knepley } 4044b5a892a1SMatthew G. Knepley *numPoints = c / 2; 4045b5a892a1SMatthew G. Knepley *points = pts; 40463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4047b5a892a1SMatthew G. Knepley } 4048b5a892a1SMatthew G. Knepley 4049d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4050d71ae5a4SJacob Faibussowitsch { 4051b5a892a1SMatthew G. Knepley DMPolytopeType ct; 4052b5a892a1SMatthew G. Knepley PetscInt *closure, *fifo; 4053b5a892a1SMatthew G. Knepley PetscInt closureSize = 0, fifoStart = 0, fifoSize = 0; 4054b5a892a1SMatthew G. Knepley PetscInt maxConeSize, maxSupportSize, coneSeries, supportSeries; 4055b5a892a1SMatthew G. Knepley PetscInt depth, maxSize; 4056b5a892a1SMatthew G. Knepley 4057b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 40589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 4059b5a892a1SMatthew G. Knepley if (depth == 1) { 40609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points)); 40613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4062b5a892a1SMatthew G. Knepley } 40639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4064476787b7SMatthew 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; 4065c306944fSJed Brown if (DMPolytopeTypeIsHybrid(ct) && ct != DM_POLYTOPE_POINT_PRISM_TENSOR) { 40669566063dSJacob Faibussowitsch PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points)); 40673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4068b5a892a1SMatthew G. Knepley } 40699566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4070b5a892a1SMatthew G. Knepley coneSeries = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1; 4071b5a892a1SMatthew G. Knepley supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1; 4072b5a892a1SMatthew G. Knepley maxSize = PetscMax(coneSeries, supportSeries); 40739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 40749371c9d4SSatish Balay if (*points) { 40759371c9d4SSatish Balay closure = *points; 40769371c9d4SSatish Balay } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure)); 4077b5a892a1SMatthew G. Knepley closure[closureSize++] = p; 4078b5a892a1SMatthew G. Knepley closure[closureSize++] = ornt; 4079b5a892a1SMatthew G. Knepley fifo[fifoSize++] = p; 4080b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ornt; 4081b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4082b5a892a1SMatthew G. Knepley /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 4083b5a892a1SMatthew G. Knepley while (fifoSize - fifoStart) { 4084b5a892a1SMatthew G. Knepley const PetscInt q = fifo[fifoStart++]; 4085b5a892a1SMatthew G. Knepley const PetscInt o = fifo[fifoStart++]; 4086b5a892a1SMatthew G. Knepley const DMPolytopeType qt = (DMPolytopeType)fifo[fifoStart++]; 408785036b15SMatthew G. Knepley const PetscInt *qarr = DMPolytopeTypeGetArrangement(qt, o); 408809015e70SStefano Zampini const PetscInt *tmp, *tmpO = NULL; 4089b5a892a1SMatthew G. Knepley PetscInt tmpSize, t; 4090b5a892a1SMatthew G. Knepley 4091b5a892a1SMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 409285036b15SMatthew G. Knepley PetscInt nO = DMPolytopeTypeGetNumArrangements(qt) / 2; 409363a3b9bcSJacob 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); 4094b5a892a1SMatthew G. Knepley } 409509015e70SStefano Zampini PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4096b5a892a1SMatthew G. Knepley for (t = 0; t < tmpSize; ++t) { 4097b5a892a1SMatthew G. Knepley const PetscInt ip = useCone && qarr ? qarr[t * 2] : t; 4098b5a892a1SMatthew G. Knepley const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0; 4099b5a892a1SMatthew G. Knepley const PetscInt cp = tmp[ip]; 41009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cp, &ct)); 4101b5a892a1SMatthew G. Knepley const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0; 4102b5a892a1SMatthew G. Knepley PetscInt c; 4103b5a892a1SMatthew G. Knepley 4104b5a892a1SMatthew G. Knepley /* Check for duplicate */ 4105b5a892a1SMatthew G. Knepley for (c = 0; c < closureSize; c += 2) { 4106b5a892a1SMatthew G. Knepley if (closure[c] == cp) break; 4107b5a892a1SMatthew G. Knepley } 4108b5a892a1SMatthew G. Knepley if (c == closureSize) { 4109b5a892a1SMatthew G. Knepley closure[closureSize++] = cp; 4110b5a892a1SMatthew G. Knepley closure[closureSize++] = co; 4111b5a892a1SMatthew G. Knepley fifo[fifoSize++] = cp; 4112b5a892a1SMatthew G. Knepley fifo[fifoSize++] = co; 4113b5a892a1SMatthew G. Knepley fifo[fifoSize++] = ct; 4114b5a892a1SMatthew G. Knepley } 4115b5a892a1SMatthew G. Knepley } 411609015e70SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO)); 4117b5a892a1SMatthew G. Knepley } 41189566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo)); 4119b5a892a1SMatthew G. Knepley if (numPoints) *numPoints = closureSize / 2; 4120b5a892a1SMatthew G. Knepley if (points) *points = closure; 41213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4122b5a892a1SMatthew G. Knepley } 4123b5a892a1SMatthew G. Knepley 4124552f7358SJed Brown /*@C 4125eaf898f9SPatrick Sanan DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG 4126552f7358SJed Brown 4127a1cb98faSBarry Smith Not Collective 4128552f7358SJed Brown 4129552f7358SJed Brown Input Parameters: 4130a1cb98faSBarry Smith + dm - The `DMPLEX` 4131b5a892a1SMatthew G. Knepley . p - The mesh point 4132a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star 4133552f7358SJed Brown 41346b867d5aSJose E. Roman Input/Output Parameter: 41356b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]; 41362c9a7b26SBarry Smith if *points is `NULL` on input, internal storage will be returned, use `DMPlexRestoreTransitiveClosure()`, 41372c9a7b26SBarry Smith otherwise the provided array is used to hold the values 41386b867d5aSJose E. Roman 41396b867d5aSJose E. Roman Output Parameter: 41402c9a7b26SBarry Smith . numPoints - The number of points in the closure, so `points` is of size 2*`numPoints` 4141552f7358SJed Brown 4142a1cb98faSBarry Smith Level: beginner 4143a1cb98faSBarry Smith 4144552f7358SJed Brown Note: 414520f4b53cSBarry Smith If using internal storage (points is `NULL` on input), each call overwrites the last output. 4146552f7358SJed Brown 414760225df5SJacob Faibussowitsch Fortran Notes: 41482c9a7b26SBarry Smith `points` must be declared with 41492c9a7b26SBarry Smith .vb 41502c9a7b26SBarry Smith PetscInt, pointer :: points(:) 41512c9a7b26SBarry Smith .ve 41522c9a7b26SBarry Smith and is always allocated by the function. 41532c9a7b26SBarry Smith 41542c9a7b26SBarry Smith The `numPoints` argument is not present in the Fortran binding. 41553813dfbdSMatthew G Knepley 41561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4157552f7358SJed Brown @*/ 4158d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4159d71ae5a4SJacob Faibussowitsch { 4160b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4161552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41624f572ea9SToby Isaac if (numPoints) PetscAssertPointer(numPoints, 4); 41634f572ea9SToby Isaac if (points) PetscAssertPointer(points, 5); 4164332e0eaaSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) { 4165332e0eaaSMatthew G. Knepley PetscInt pStart, pEnd; 4166332e0eaaSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4167332e0eaaSMatthew G. Knepley PetscCheck(p >= pStart && p < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd); 4168332e0eaaSMatthew G. Knepley } 41699566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points)); 41703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41719bf0dad6SMatthew G. Knepley } 41729bf0dad6SMatthew G. Knepley 4173552f7358SJed Brown /*@C 4174eaf898f9SPatrick Sanan DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG 4175552f7358SJed Brown 4176a1cb98faSBarry Smith Not Collective 4177552f7358SJed Brown 4178552f7358SJed Brown Input Parameters: 4179a1cb98faSBarry Smith + dm - The `DMPLEX` 4180b5a892a1SMatthew G. Knepley . p - The mesh point 4181a1cb98faSBarry Smith . useCone - `PETSC_TRUE` for the closure, otherwise return the star 418220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints` 4183b5a892a1SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 4184552f7358SJed Brown 4185a1cb98faSBarry Smith Level: beginner 4186a1cb98faSBarry Smith 4187552f7358SJed Brown Note: 418820f4b53cSBarry Smith If not using internal storage (points is not `NULL` on input), this call is unnecessary 4189552f7358SJed Brown 41901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()` 4191552f7358SJed Brown @*/ 4192d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 4193d71ae5a4SJacob Faibussowitsch { 4194b5a892a1SMatthew G. Knepley PetscFunctionBeginHot; 4195552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 41964ff43b2cSJed Brown if (numPoints) *numPoints = 0; 41979566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points)); 41983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4199552f7358SJed Brown } 4200552f7358SJed Brown 4201552f7358SJed Brown /*@ 4202eaf898f9SPatrick Sanan DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG 4203552f7358SJed Brown 4204a1cb98faSBarry Smith Not Collective 4205552f7358SJed Brown 4206552f7358SJed Brown Input Parameter: 420760225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4208552f7358SJed Brown 4209552f7358SJed Brown Output Parameters: 4210552f7358SJed Brown + maxConeSize - The maximum number of in-edges 4211552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 4212552f7358SJed Brown 4213552f7358SJed Brown Level: beginner 4214552f7358SJed Brown 42151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()` 4216552f7358SJed Brown @*/ 4217d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 4218d71ae5a4SJacob Faibussowitsch { 4219552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4220552f7358SJed Brown 4221552f7358SJed Brown PetscFunctionBegin; 4222552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42231baa6e33SBarry Smith if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize)); 42241baa6e33SBarry Smith if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize)); 42253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4226552f7358SJed Brown } 4227552f7358SJed Brown 4228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm) 4229d71ae5a4SJacob Faibussowitsch { 4230552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 42316302a7fbSVaclav Hapla PetscInt size, maxSupportSize; 4232552f7358SJed Brown 4233552f7358SJed Brown PetscFunctionBegin; 4234552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->coneSection)); 42369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size)); 42379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->cones)); 42389566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(size, &mesh->coneOrientations)); 42396302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 42406302a7fbSVaclav Hapla if (maxSupportSize) { 42419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 42429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size)); 42439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &mesh->supports)); 4244552f7358SJed Brown } 42453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4246552f7358SJed Brown } 4247552f7358SJed Brown 4248d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) 4249d71ae5a4SJacob Faibussowitsch { 4250552f7358SJed Brown PetscFunctionBegin; 42519566063dSJacob Faibussowitsch if (subdm) PetscCall(DMClone(dm, subdm)); 4252dd072f5fSMatthew G. Knepley PetscCall(DMCreateSectionSubDM(dm, numFields, fields, NULL, NULL, is, subdm)); 4253ad540459SPierre Jolivet if (subdm) (*subdm)->useNatural = dm->useNatural; 4254736995cdSBlaise Bourdin if (dm->useNatural && dm->sfMigration) { 425595602cf2SAlexis Marboeuf PetscSF sfNatural; 4256f94b4a02SBlaise Bourdin 42573dcd263cSBlaise Bourdin (*subdm)->sfMigration = dm->sfMigration; 42589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm->sfMigration)); 425995602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural)); 4260c40e9495SBlaise Bourdin (*subdm)->sfNatural = sfNatural; 4261f94b4a02SBlaise Bourdin } 42623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4263552f7358SJed Brown } 4264552f7358SJed Brown 4265d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) 4266d71ae5a4SJacob Faibussowitsch { 42673dcd263cSBlaise Bourdin PetscInt i = 0; 42682adcc780SMatthew G. Knepley 42692adcc780SMatthew G. Knepley PetscFunctionBegin; 42709566063dSJacob Faibussowitsch PetscCall(DMClone(dms[0], superdm)); 42719566063dSJacob Faibussowitsch PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm)); 4272c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_FALSE; 42733dcd263cSBlaise Bourdin for (i = 0; i < len; i++) { 42743dcd263cSBlaise Bourdin if (dms[i]->useNatural && dms[i]->sfMigration) { 427595602cf2SAlexis Marboeuf PetscSF sfNatural; 42763dcd263cSBlaise Bourdin 42773dcd263cSBlaise Bourdin (*superdm)->sfMigration = dms[i]->sfMigration; 42789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration)); 4279c40e9495SBlaise Bourdin (*superdm)->useNatural = PETSC_TRUE; 428095602cf2SAlexis Marboeuf PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural)); 4281c40e9495SBlaise Bourdin (*superdm)->sfNatural = sfNatural; 42823dcd263cSBlaise Bourdin break; 42833dcd263cSBlaise Bourdin } 42843dcd263cSBlaise Bourdin } 42853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42862adcc780SMatthew G. Knepley } 42872adcc780SMatthew G. Knepley 4288552f7358SJed Brown /*@ 4289eaf898f9SPatrick Sanan DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information 4290552f7358SJed Brown 4291a1cb98faSBarry Smith Not Collective 4292552f7358SJed Brown 4293552f7358SJed Brown Input Parameter: 429460225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4295552f7358SJed Brown 4296552f7358SJed Brown Level: beginner 4297552f7358SJed Brown 4298a1cb98faSBarry Smith Note: 4299a1cb98faSBarry Smith This should be called after all calls to `DMPlexSetCone()` 4300a1cb98faSBarry Smith 43011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()` 4302552f7358SJed Brown @*/ 4303d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm) 4304d71ae5a4SJacob Faibussowitsch { 4305552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4306552f7358SJed Brown PetscInt *offsets; 4307552f7358SJed Brown PetscInt supportSize; 4308552f7358SJed Brown PetscInt pStart, pEnd, p; 4309552f7358SJed Brown 4310552f7358SJed Brown PetscFunctionBegin; 4311552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 431228b400f6SJacob Faibussowitsch PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 43139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0)); 4314552f7358SJed Brown /* Calculate support sizes */ 43159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4316552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4317552f7358SJed Brown PetscInt dof, off, c; 4318552f7358SJed Brown 43199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 43209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 432148a46eb9SPierre Jolivet for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1)); 4322552f7358SJed Brown } 43239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(mesh->supportSection)); 4324552f7358SJed Brown /* Calculate supports */ 43259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize)); 43269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(supportSize, &mesh->supports)); 43279566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pEnd - pStart, &offsets)); 4328552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 4329552f7358SJed Brown PetscInt dof, off, c; 4330552f7358SJed Brown 43319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof)); 43329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off)); 4333552f7358SJed Brown for (c = off; c < off + dof; ++c) { 4334552f7358SJed Brown const PetscInt q = mesh->cones[c]; 4335552f7358SJed Brown PetscInt offS; 4336552f7358SJed Brown 43379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS)); 43380d644c17SKarl Rupp 4339552f7358SJed Brown mesh->supports[offS + offsets[q]] = p; 4340552f7358SJed Brown ++offsets[q]; 4341552f7358SJed Brown } 4342552f7358SJed Brown } 43439566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 43449566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0)); 43453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4346552f7358SJed Brown } 4347552f7358SJed Brown 4348d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) 4349d71ae5a4SJacob Faibussowitsch { 4350277ea44aSLisandro Dalcin IS stratumIS; 4351277ea44aSLisandro Dalcin 4352277ea44aSLisandro Dalcin PetscFunctionBegin; 43533ba16761SJacob Faibussowitsch if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS); 435476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 4355277ea44aSLisandro Dalcin PetscInt qStart, qEnd, numLevels, level; 4356277ea44aSLisandro Dalcin PetscBool overlap = PETSC_FALSE; 43579566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numLevels)); 4358277ea44aSLisandro Dalcin for (level = 0; level < numLevels; level++) { 43599566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 43609371c9d4SSatish Balay if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) { 43619371c9d4SSatish Balay overlap = PETSC_TRUE; 43629371c9d4SSatish Balay break; 43639371c9d4SSatish Balay } 4364277ea44aSLisandro Dalcin } 436563a3b9bcSJacob 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); 4366277ea44aSLisandro Dalcin } 43679566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS)); 43689566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(label, depth, stratumIS)); 43699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&stratumIS)); 43703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4371277ea44aSLisandro Dalcin } 4372277ea44aSLisandro Dalcin 4373e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_CellType_Private(DM dm, DMLabel label) 4374e91fa0a1SMatthew G. Knepley { 4375e91fa0a1SMatthew G. Knepley PetscInt *pMin, *pMax; 4376e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4377e91fa0a1SMatthew G. Knepley PetscInt dmin = PETSC_MAX_INT, dmax = PETSC_MIN_INT; 4378e91fa0a1SMatthew G. Knepley 4379e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4380e91fa0a1SMatthew G. Knepley { 4381e91fa0a1SMatthew G. Knepley DMLabel label2; 4382e91fa0a1SMatthew G. Knepley 4383e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellTypeLabel(dm, &label2)); 4384e91fa0a1SMatthew G. Knepley PetscCall(PetscObjectViewFromOptions((PetscObject)label2, NULL, "-ct_view")); 4385e91fa0a1SMatthew G. Knepley } 4386e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4387e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4388e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4389e91fa0a1SMatthew G. Knepley 4390e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4391e91fa0a1SMatthew G. Knepley dmin = PetscMin(DMPolytopeTypeGetDim(ct), dmin); 4392e91fa0a1SMatthew G. Knepley dmax = PetscMax(DMPolytopeTypeGetDim(ct), dmax); 4393e91fa0a1SMatthew G. Knepley } 4394e91fa0a1SMatthew G. Knepley PetscCall(PetscMalloc2(dmax + 1, &pMin, dmax + 1, &pMax)); 4395e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4396e91fa0a1SMatthew G. Knepley pMin[d] = PETSC_MAX_INT; 4397e91fa0a1SMatthew G. Knepley pMax[d] = PETSC_MIN_INT; 4398e91fa0a1SMatthew G. Knepley } 4399e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4400e91fa0a1SMatthew G. Knepley DMPolytopeType ct; 4401e91fa0a1SMatthew G. Knepley PetscInt d; 4402e91fa0a1SMatthew G. Knepley 4403e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetCellType(dm, p, &ct)); 4404e91fa0a1SMatthew G. Knepley d = DMPolytopeTypeGetDim(ct); 4405e91fa0a1SMatthew G. Knepley pMin[d] = PetscMin(p, pMin[d]); 4406e91fa0a1SMatthew G. Knepley pMax[d] = PetscMax(p, pMax[d]); 4407e91fa0a1SMatthew G. Knepley } 4408e91fa0a1SMatthew G. Knepley for (PetscInt d = dmin; d <= dmax; ++d) { 4409e91fa0a1SMatthew G. Knepley if (pMin[d] > pMax[d]) continue; 4410e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, d, pMin[d], pMax[d] + 1)); 4411e91fa0a1SMatthew G. Knepley } 4412e91fa0a1SMatthew G. Knepley PetscCall(PetscFree2(pMin, pMax)); 4413e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4414e91fa0a1SMatthew G. Knepley } 4415e91fa0a1SMatthew G. Knepley 4416e91fa0a1SMatthew G. Knepley static PetscErrorCode DMPlexStratify_Topological_Private(DM dm, DMLabel label) 4417e91fa0a1SMatthew G. Knepley { 4418e91fa0a1SMatthew G. Knepley PetscInt pStart, pEnd; 4419e91fa0a1SMatthew G. Knepley PetscInt numRoots = 0, numLeaves = 0; 4420e91fa0a1SMatthew G. Knepley 4421e91fa0a1SMatthew G. Knepley PetscFunctionBegin; 4422e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4423e91fa0a1SMatthew G. Knepley { 4424e91fa0a1SMatthew G. Knepley /* Initialize roots and count leaves */ 4425e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4426e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4427e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4428e91fa0a1SMatthew G. Knepley 4429e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4430e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4431e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4432e91fa0a1SMatthew G. Knepley if (!coneSize && supportSize) { 4433e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4434e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4435e91fa0a1SMatthew G. Knepley ++numRoots; 4436e91fa0a1SMatthew G. Knepley } else if (!supportSize && coneSize) { 4437e91fa0a1SMatthew G. Knepley ++numLeaves; 4438e91fa0a1SMatthew G. Knepley } else if (!supportSize && !coneSize) { 4439e91fa0a1SMatthew G. Knepley /* Isolated points */ 4440e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4441e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4442e91fa0a1SMatthew G. Knepley } 4443e91fa0a1SMatthew G. Knepley } 4444e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1)); 4445e91fa0a1SMatthew G. Knepley } 4446e91fa0a1SMatthew G. Knepley 4447e91fa0a1SMatthew G. Knepley if (numRoots + numLeaves == (pEnd - pStart)) { 4448e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4449e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4450e91fa0a1SMatthew G. Knepley PetscInt coneSize, supportSize; 4451e91fa0a1SMatthew G. Knepley 4452e91fa0a1SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 4453e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4454e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 4455e91fa0a1SMatthew G. Knepley if (!supportSize && coneSize) { 4456e91fa0a1SMatthew G. Knepley sMin = PetscMin(p, sMin); 4457e91fa0a1SMatthew G. Knepley sMax = PetscMax(p, sMax); 4458e91fa0a1SMatthew G. Knepley } 4459e91fa0a1SMatthew G. Knepley } 4460e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1)); 4461e91fa0a1SMatthew G. Knepley } else { 4462e91fa0a1SMatthew G. Knepley PetscInt level = 0; 4463e91fa0a1SMatthew G. Knepley PetscInt qStart, qEnd; 4464e91fa0a1SMatthew G. Knepley 4465e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4466e91fa0a1SMatthew G. Knepley while (qEnd > qStart) { 4467e91fa0a1SMatthew G. Knepley PetscInt sMin = PETSC_MAX_INT; 4468e91fa0a1SMatthew G. Knepley PetscInt sMax = PETSC_MIN_INT; 4469e91fa0a1SMatthew G. Knepley 4470e91fa0a1SMatthew G. Knepley for (PetscInt q = qStart; q < qEnd; ++q) { 4471e91fa0a1SMatthew G. Knepley const PetscInt *support; 4472e91fa0a1SMatthew G. Knepley PetscInt supportSize; 4473e91fa0a1SMatthew G. Knepley 4474e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, q, &supportSize)); 4475e91fa0a1SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, q, &support)); 4476e91fa0a1SMatthew G. Knepley for (PetscInt s = 0; s < supportSize; ++s) { 4477e91fa0a1SMatthew G. Knepley sMin = PetscMin(support[s], sMin); 4478e91fa0a1SMatthew G. Knepley sMax = PetscMax(support[s], sMax); 4479e91fa0a1SMatthew G. Knepley } 4480e91fa0a1SMatthew G. Knepley } 4481e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &level)); 4482e91fa0a1SMatthew G. Knepley PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1)); 4483e91fa0a1SMatthew G. Knepley PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd)); 4484e91fa0a1SMatthew G. Knepley } 4485e91fa0a1SMatthew G. Knepley } 4486e91fa0a1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 4487e91fa0a1SMatthew G. Knepley } 4488e91fa0a1SMatthew G. Knepley 4489552f7358SJed Brown /*@ 4490a4e35b19SJacob Faibussowitsch DMPlexStratify - Computes the strata for all points in the `DMPLEX` 4491552f7358SJed Brown 449220f4b53cSBarry Smith Collective 4493552f7358SJed Brown 4494552f7358SJed Brown Input Parameter: 449560225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4496552f7358SJed Brown 4497a1cb98faSBarry Smith Level: beginner 4498552f7358SJed Brown 4499552f7358SJed Brown Notes: 4500a4e35b19SJacob Faibussowitsch The strata group all points of the same grade, and this function calculates the strata. This 4501a4e35b19SJacob Faibussowitsch grade can be seen as the height (or depth) of the point in the DAG. 4502a4e35b19SJacob Faibussowitsch 4503a4e35b19SJacob Faibussowitsch The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and 4504a4e35b19SJacob Faibussowitsch can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). 4505a1cb98faSBarry Smith Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex 4506b1bb481bSMatthew 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 4507a1cb98faSBarry Smith until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or 4508a1cb98faSBarry Smith manually via `DMGetLabel()`. The height is defined implicitly by height = maxDimension - depth, and can be accessed 4509a1cb98faSBarry Smith via `DMPlexGetHeightStratum()`. For example, cells have height 0 and faces have height 1. 4510552f7358SJed Brown 4511b1bb481bSMatthew Knepley The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results 4512b1bb481bSMatthew Knepley if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that 4513b1bb481bSMatthew 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 4514b1bb481bSMatthew Knepley to interpolate only that one (e0), so that 4515a1cb98faSBarry Smith .vb 4516a1cb98faSBarry Smith cone(c0) = {e0, v2} 4517a1cb98faSBarry Smith cone(e0) = {v0, v1} 4518a1cb98faSBarry Smith .ve 4519a1cb98faSBarry Smith If `DMPlexStratify()` is run on this mesh, it will give depths 4520a1cb98faSBarry Smith .vb 4521a1cb98faSBarry Smith depth 0 = {v0, v1, v2} 4522a1cb98faSBarry Smith depth 1 = {e0, c0} 4523a1cb98faSBarry Smith .ve 4524b1bb481bSMatthew Knepley where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2. 4525b1bb481bSMatthew Knepley 4526a1cb98faSBarry Smith `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()` 4527552f7358SJed Brown 45281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()` 4529552f7358SJed Brown @*/ 4530d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm) 4531d71ae5a4SJacob Faibussowitsch { 4532df0420ecSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4533aa50250dSMatthew G. Knepley DMLabel label; 4534e91fa0a1SMatthew G. Knepley PetscBool flg = PETSC_FALSE; 4535552f7358SJed Brown 4536552f7358SJed Brown PetscFunctionBegin; 4537552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 45389566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0)); 4539277ea44aSLisandro Dalcin 4540e91fa0a1SMatthew G. Knepley // Create depth label 4541d28dd301SMatthew G. Knepley PetscCall(DMRemoveLabel(dm, "depth", NULL)); 45429566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "depth")); 45439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 4544277ea44aSLisandro Dalcin 4545e91fa0a1SMatthew G. Knepley PetscCall(PetscOptionsGetBool(NULL, dm->hdr.prefix, "-dm_plex_stratify_celltype", &flg, NULL)); 4546e91fa0a1SMatthew G. Knepley if (flg) PetscCall(DMPlexStratify_CellType_Private(dm, label)); 4547e91fa0a1SMatthew G. Knepley else PetscCall(DMPlexStratify_Topological_Private(dm, label)); 4548552f7358SJed Brown 4549bf4602e4SToby Isaac { /* just in case there is an empty process */ 4550bf4602e4SToby Isaac PetscInt numValues, maxValues = 0, v; 4551bf4602e4SToby Isaac 45529566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4553712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 455448a46eb9SPierre Jolivet for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v)); 4555bf4602e4SToby Isaac } 45569566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState)); 45579566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0)); 45583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4559552f7358SJed Brown } 4560552f7358SJed Brown 4561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) 4562d71ae5a4SJacob Faibussowitsch { 4563412e9a14SMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4564412e9a14SMatthew G. Knepley PetscInt dim, depth, pheight, coneSize; 4565ba2698f1SMatthew G. Knepley 4566412e9a14SMatthew G. Knepley PetscFunctionBeginHot; 45679566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 45689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 45699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 4570ba2698f1SMatthew G. Knepley pheight = depth - pdepth; 4571ba2698f1SMatthew G. Knepley if (depth <= 1) { 4572ba2698f1SMatthew G. Knepley switch (pdepth) { 4573d71ae5a4SJacob Faibussowitsch case 0: 4574d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_POINT; 4575d71ae5a4SJacob Faibussowitsch break; 4576ba2698f1SMatthew G. Knepley case 1: 4577ba2698f1SMatthew G. Knepley switch (coneSize) { 4578d71ae5a4SJacob Faibussowitsch case 2: 4579d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4580d71ae5a4SJacob Faibussowitsch break; 4581d71ae5a4SJacob Faibussowitsch case 3: 4582d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4583d71ae5a4SJacob Faibussowitsch break; 4584ba2698f1SMatthew G. Knepley case 4: 4585ba2698f1SMatthew G. Knepley switch (dim) { 4586d71ae5a4SJacob Faibussowitsch case 2: 4587d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4588d71ae5a4SJacob Faibussowitsch break; 4589d71ae5a4SJacob Faibussowitsch case 3: 4590d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4591d71ae5a4SJacob Faibussowitsch break; 4592d71ae5a4SJacob Faibussowitsch default: 4593d71ae5a4SJacob Faibussowitsch break; 4594ba2698f1SMatthew G. Knepley } 4595ba2698f1SMatthew G. Knepley break; 4596d71ae5a4SJacob Faibussowitsch case 5: 4597d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4598d71ae5a4SJacob Faibussowitsch break; 4599d71ae5a4SJacob Faibussowitsch case 6: 4600d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4601d71ae5a4SJacob Faibussowitsch break; 4602d71ae5a4SJacob Faibussowitsch case 8: 4603d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4604d71ae5a4SJacob Faibussowitsch break; 4605d71ae5a4SJacob Faibussowitsch default: 4606d71ae5a4SJacob Faibussowitsch break; 4607ba2698f1SMatthew G. Knepley } 4608ba2698f1SMatthew G. Knepley } 4609ba2698f1SMatthew G. Knepley } else { 4610ba2698f1SMatthew G. Knepley if (pdepth == 0) { 4611ba2698f1SMatthew G. Knepley ct = DM_POLYTOPE_POINT; 4612ba2698f1SMatthew G. Knepley } else if (pheight == 0) { 4613ba2698f1SMatthew G. Knepley switch (dim) { 4614ba2698f1SMatthew G. Knepley case 1: 4615ba2698f1SMatthew G. Knepley switch (coneSize) { 4616d71ae5a4SJacob Faibussowitsch case 2: 4617d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4618d71ae5a4SJacob Faibussowitsch break; 4619d71ae5a4SJacob Faibussowitsch default: 4620d71ae5a4SJacob Faibussowitsch break; 4621ba2698f1SMatthew G. Knepley } 4622ba2698f1SMatthew G. Knepley break; 4623ba2698f1SMatthew G. Knepley case 2: 4624ba2698f1SMatthew G. Knepley switch (coneSize) { 4625d71ae5a4SJacob Faibussowitsch case 3: 4626d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4627d71ae5a4SJacob Faibussowitsch break; 4628d71ae5a4SJacob Faibussowitsch case 4: 4629d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4630d71ae5a4SJacob Faibussowitsch break; 4631d71ae5a4SJacob Faibussowitsch default: 4632d71ae5a4SJacob Faibussowitsch break; 4633ba2698f1SMatthew G. Knepley } 4634ba2698f1SMatthew G. Knepley break; 4635ba2698f1SMatthew G. Knepley case 3: 4636ba2698f1SMatthew G. Knepley switch (coneSize) { 4637d71ae5a4SJacob Faibussowitsch case 4: 4638d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TETRAHEDRON; 4639d71ae5a4SJacob Faibussowitsch break; 46409371c9d4SSatish Balay case 5: { 4641da9060c4SMatthew G. Knepley const PetscInt *cone; 4642da9060c4SMatthew G. Knepley PetscInt faceConeSize; 4643da9060c4SMatthew G. Knepley 46449566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 46459566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize)); 4646da9060c4SMatthew G. Knepley switch (faceConeSize) { 4647d71ae5a4SJacob Faibussowitsch case 3: 4648d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRI_PRISM_TENSOR; 4649d71ae5a4SJacob Faibussowitsch break; 4650d71ae5a4SJacob Faibussowitsch case 4: 4651d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_PYRAMID; 4652d71ae5a4SJacob Faibussowitsch break; 4653da9060c4SMatthew G. Knepley } 46549371c9d4SSatish Balay } break; 4655d71ae5a4SJacob Faibussowitsch case 6: 4656d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_HEXAHEDRON; 4657d71ae5a4SJacob Faibussowitsch break; 4658d71ae5a4SJacob Faibussowitsch default: 4659d71ae5a4SJacob Faibussowitsch break; 4660ba2698f1SMatthew G. Knepley } 4661ba2698f1SMatthew G. Knepley break; 4662d71ae5a4SJacob Faibussowitsch default: 4663d71ae5a4SJacob Faibussowitsch break; 4664ba2698f1SMatthew G. Knepley } 4665ba2698f1SMatthew G. Knepley } else if (pheight > 0) { 4666ba2698f1SMatthew G. Knepley switch (coneSize) { 4667d71ae5a4SJacob Faibussowitsch case 2: 4668d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_SEGMENT; 4669d71ae5a4SJacob Faibussowitsch break; 4670d71ae5a4SJacob Faibussowitsch case 3: 4671d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_TRIANGLE; 4672d71ae5a4SJacob Faibussowitsch break; 4673d71ae5a4SJacob Faibussowitsch case 4: 4674d71ae5a4SJacob Faibussowitsch ct = DM_POLYTOPE_QUADRILATERAL; 4675d71ae5a4SJacob Faibussowitsch break; 4676d71ae5a4SJacob Faibussowitsch default: 4677d71ae5a4SJacob Faibussowitsch break; 4678ba2698f1SMatthew G. Knepley } 4679ba2698f1SMatthew G. Knepley } 4680ba2698f1SMatthew G. Knepley } 4681412e9a14SMatthew G. Knepley *pt = ct; 46823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4683ba2698f1SMatthew G. Knepley } 4684412e9a14SMatthew G. Knepley 4685412e9a14SMatthew G. Knepley /*@ 4686412e9a14SMatthew G. Knepley DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size. 4687412e9a14SMatthew G. Knepley 468820f4b53cSBarry Smith Collective 4689412e9a14SMatthew G. Knepley 4690412e9a14SMatthew G. Knepley Input Parameter: 469160225df5SJacob Faibussowitsch . dm - The `DMPLEX` 4692412e9a14SMatthew G. Knepley 4693412e9a14SMatthew G. Knepley Level: developer 4694412e9a14SMatthew G. Knepley 4695a1cb98faSBarry Smith Note: 4696a1cb98faSBarry Smith This function is normally called automatically when a cell type is requested. It creates an 4697a1cb98faSBarry Smith internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable 4698a1cb98faSBarry Smith automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype"). 4699412e9a14SMatthew G. Knepley 4700a1cb98faSBarry Smith `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()` 4701a1cb98faSBarry Smith 47021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()` 4703412e9a14SMatthew G. Knepley @*/ 4704d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm) 4705d71ae5a4SJacob Faibussowitsch { 4706412e9a14SMatthew G. Knepley DM_Plex *mesh; 4707412e9a14SMatthew G. Knepley DMLabel ctLabel; 4708412e9a14SMatthew G. Knepley PetscInt pStart, pEnd, p; 4709412e9a14SMatthew G. Knepley 4710412e9a14SMatthew G. Knepley PetscFunctionBegin; 4711412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4712412e9a14SMatthew G. Knepley mesh = (DM_Plex *)dm->data; 47139566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 47149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 47159566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 471621027e53SStefano Zampini PetscCall(PetscFree(mesh->cellTypes)); 471721027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 4718412e9a14SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 4719327c2912SStefano Zampini DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 4720412e9a14SMatthew G. Knepley PetscInt pdepth; 4721412e9a14SMatthew G. Knepley 47229566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, p, &pdepth)); 47239566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct)); 4724841fc1b7SMatthew 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 " has invalid celltype (%s)", p, DMPolytopeTypes[ct]); 47259566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ctLabel, p, ct)); 4726*6497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 4727412e9a14SMatthew G. Knepley } 47289566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState)); 47299566063dSJacob Faibussowitsch PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view")); 47303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4731ba2698f1SMatthew G. Knepley } 4732ba2698f1SMatthew G. Knepley 4733552f7358SJed Brown /*@C 4734552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 4735552f7358SJed Brown 4736552f7358SJed Brown Not Collective 4737552f7358SJed Brown 4738552f7358SJed Brown Input Parameters: 4739a1cb98faSBarry Smith + dm - The `DMPLEX` object 4740552f7358SJed Brown . numPoints - The number of input points for the join 4741552f7358SJed Brown - points - The input points 4742552f7358SJed Brown 4743552f7358SJed Brown Output Parameters: 4744552f7358SJed Brown + numCoveredPoints - The number of points in the join 4745552f7358SJed Brown - coveredPoints - The points in the join 4746552f7358SJed Brown 4747552f7358SJed Brown Level: intermediate 4748552f7358SJed Brown 4749a1cb98faSBarry Smith Note: 4750a1cb98faSBarry Smith Currently, this is restricted to a single level join 4751552f7358SJed Brown 475260225df5SJacob Faibussowitsch Fortran Notes: 47532c9a7b26SBarry Smith `converedPoints` must be declared with 47542c9a7b26SBarry Smith .vb 47552c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 47562c9a7b26SBarry Smith .ve 47572c9a7b26SBarry Smith 47582c9a7b26SBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding. 47593813dfbdSMatthew G Knepley 47601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4761552f7358SJed Brown @*/ 47625d83a8b1SBarry Smith PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4763d71ae5a4SJacob Faibussowitsch { 4764552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4765552f7358SJed Brown PetscInt *join[2]; 4766552f7358SJed Brown PetscInt joinSize, i = 0; 4767552f7358SJed Brown PetscInt dof, off, p, c, m; 47686302a7fbSVaclav Hapla PetscInt maxSupportSize; 4769552f7358SJed Brown 4770552f7358SJed Brown PetscFunctionBegin; 4771552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 47724f572ea9SToby Isaac PetscAssertPointer(points, 3); 47734f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 47744f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 47756302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize)); 47766302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0])); 47776302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1])); 4778552f7358SJed Brown /* Copy in support of first point */ 47799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof)); 47809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off)); 4781ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize]; 4782552f7358SJed Brown /* Check each successive support */ 4783552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4784552f7358SJed Brown PetscInt newJoinSize = 0; 4785552f7358SJed Brown 47869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof)); 47879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off)); 4788552f7358SJed Brown for (c = 0; c < dof; ++c) { 4789552f7358SJed Brown const PetscInt point = mesh->supports[off + c]; 4790552f7358SJed Brown 4791552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4792552f7358SJed Brown if (point == join[i][m]) { 4793552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4794552f7358SJed Brown break; 4795552f7358SJed Brown } 4796552f7358SJed Brown } 4797552f7358SJed Brown } 4798552f7358SJed Brown joinSize = newJoinSize; 4799552f7358SJed Brown i = 1 - i; 4800552f7358SJed Brown } 4801552f7358SJed Brown *numCoveredPoints = joinSize; 4802552f7358SJed Brown *coveredPoints = join[i]; 48036302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i])); 48043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4805552f7358SJed Brown } 4806552f7358SJed Brown 4807552f7358SJed Brown /*@C 48082c9a7b26SBarry Smith DMPlexRestoreJoin - Restore an array for the join of the set of points obtained with `DMPlexGetJoin()` 4809552f7358SJed Brown 4810552f7358SJed Brown Not Collective 4811552f7358SJed Brown 4812552f7358SJed Brown Input Parameters: 4813a1cb98faSBarry Smith + dm - The `DMPLEX` object 4814552f7358SJed Brown . numPoints - The number of input points for the join 4815552f7358SJed Brown - points - The input points 4816552f7358SJed Brown 4817552f7358SJed Brown Output Parameters: 4818552f7358SJed Brown + numCoveredPoints - The number of points in the join 4819552f7358SJed Brown - coveredPoints - The points in the join 4820552f7358SJed Brown 4821552f7358SJed Brown Level: intermediate 4822552f7358SJed Brown 482360225df5SJacob Faibussowitsch Fortran Notes: 482420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 4825a1cb98faSBarry Smith 48261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()` 4827552f7358SJed Brown @*/ 48282c9a7b26SBarry Smith PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4829d71ae5a4SJacob Faibussowitsch { 4830552f7358SJed Brown PetscFunctionBegin; 4831552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48324f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 48334f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 48344f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 48359566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 4836d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 48373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4838552f7358SJed Brown } 4839552f7358SJed Brown 4840552f7358SJed Brown /*@C 4841552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 4842552f7358SJed Brown 4843552f7358SJed Brown Not Collective 4844552f7358SJed Brown 4845552f7358SJed Brown Input Parameters: 4846a1cb98faSBarry Smith + dm - The `DMPLEX` object 4847552f7358SJed Brown . numPoints - The number of input points for the join 48482c9a7b26SBarry Smith - points - The input points, its length is `numPoints` 4849552f7358SJed Brown 4850552f7358SJed Brown Output Parameters: 4851552f7358SJed Brown + numCoveredPoints - The number of points in the join 48522c9a7b26SBarry Smith - coveredPoints - The points in the join, its length is `numCoveredPoints` 4853552f7358SJed Brown 4854552f7358SJed Brown Level: intermediate 4855552f7358SJed Brown 485660225df5SJacob Faibussowitsch Fortran Notes: 48572c9a7b26SBarry Smith `points` and `converedPoints` must be declared with 48582c9a7b26SBarry Smith .vb 48592c9a7b26SBarry Smith PetscInt, pointer :: points(:) 48602c9a7b26SBarry Smith PetscInt, pointer :: coveredPints(:) 48612c9a7b26SBarry Smith .ve 48622c9a7b26SBarry Smith 48632c9a7b26SBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding. 4864a1cb98faSBarry Smith 48651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()` 4866552f7358SJed Brown @*/ 48675d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 4868d71ae5a4SJacob Faibussowitsch { 4869552f7358SJed Brown PetscInt *offsets, **closures; 4870552f7358SJed Brown PetscInt *join[2]; 4871552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 487224c766afSToby Isaac PetscInt p, d, c, m, ms; 4873552f7358SJed Brown 4874552f7358SJed Brown PetscFunctionBegin; 4875552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 48764f572ea9SToby Isaac PetscAssertPointer(points, 3); 48774f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 48784f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 4879552f7358SJed Brown 48809566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 48819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numPoints, &closures)); 48829566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 48836302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms)); 488424c766afSToby Isaac maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1; 48859566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0])); 48869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1])); 4887552f7358SJed Brown 4888552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 4889552f7358SJed Brown PetscInt closureSize; 4890552f7358SJed Brown 48919566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p])); 48920d644c17SKarl Rupp 4893552f7358SJed Brown offsets[p * (depth + 2) + 0] = 0; 4894552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4895552f7358SJed Brown PetscInt pStart, pEnd, i; 4896552f7358SJed Brown 48979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 4898552f7358SJed Brown for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) { 4899552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 4900552f7358SJed Brown offsets[p * (depth + 2) + d + 1] = i; 4901552f7358SJed Brown break; 4902552f7358SJed Brown } 4903552f7358SJed Brown } 4904552f7358SJed Brown if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i; 4905552f7358SJed Brown } 490663a3b9bcSJacob 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); 4907552f7358SJed Brown } 4908552f7358SJed Brown for (d = 0; d < depth + 1; ++d) { 4909552f7358SJed Brown PetscInt dof; 4910552f7358SJed Brown 4911552f7358SJed Brown /* Copy in support of first point */ 4912552f7358SJed Brown dof = offsets[d + 1] - offsets[d]; 4913ad540459SPierre Jolivet for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2]; 4914552f7358SJed Brown /* Check each successive cone */ 4915552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 4916552f7358SJed Brown PetscInt newJoinSize = 0; 4917552f7358SJed Brown 4918552f7358SJed Brown dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d]; 4919552f7358SJed Brown for (c = 0; c < dof; ++c) { 4920552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2]; 4921552f7358SJed Brown 4922552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 4923552f7358SJed Brown if (point == join[i][m]) { 4924552f7358SJed Brown join[1 - i][newJoinSize++] = point; 4925552f7358SJed Brown break; 4926552f7358SJed Brown } 4927552f7358SJed Brown } 4928552f7358SJed Brown } 4929552f7358SJed Brown joinSize = newJoinSize; 4930552f7358SJed Brown i = 1 - i; 4931552f7358SJed Brown } 4932552f7358SJed Brown if (joinSize) break; 4933552f7358SJed Brown } 4934552f7358SJed Brown *numCoveredPoints = joinSize; 4935552f7358SJed Brown *coveredPoints = join[i]; 493648a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p])); 49379566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 49389566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets)); 49396302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i])); 49403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4941552f7358SJed Brown } 4942552f7358SJed Brown 4943552f7358SJed Brown /*@C 4944552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 4945552f7358SJed Brown 4946552f7358SJed Brown Not Collective 4947552f7358SJed Brown 4948552f7358SJed Brown Input Parameters: 4949a1cb98faSBarry Smith + dm - The `DMPLEX` object 4950552f7358SJed Brown . numPoints - The number of input points for the meet 49512c9a7b26SBarry Smith - points - The input points, of length `numPoints` 4952552f7358SJed Brown 4953552f7358SJed Brown Output Parameters: 495460225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet 49552c9a7b26SBarry Smith - coveringPoints - The points in the meet, of length `numCoveringPoints` 4956552f7358SJed Brown 4957552f7358SJed Brown Level: intermediate 4958552f7358SJed Brown 4959a1cb98faSBarry Smith Note: 4960a1cb98faSBarry Smith Currently, this is restricted to a single level meet 4961552f7358SJed Brown 49623813dfbdSMatthew G Knepley Fortran Notes: 49632c9a7b26SBarry Smith `coveringPoints` must be declared with 49642c9a7b26SBarry Smith .vb 49652c9a7b26SBarry Smith PetscInt, pointer :: coveringPoints(:) 49662c9a7b26SBarry Smith .ve 49672c9a7b26SBarry Smith 496820f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 49693813dfbdSMatthew G Knepley 49701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 4971552f7358SJed Brown @*/ 49725d83a8b1SBarry Smith PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt *coveringPoints[]) 4973d71ae5a4SJacob Faibussowitsch { 4974552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 4975552f7358SJed Brown PetscInt *meet[2]; 4976552f7358SJed Brown PetscInt meetSize, i = 0; 4977552f7358SJed Brown PetscInt dof, off, p, c, m; 49786302a7fbSVaclav Hapla PetscInt maxConeSize; 4979552f7358SJed Brown 4980552f7358SJed Brown PetscFunctionBegin; 4981552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 49824f572ea9SToby Isaac PetscAssertPointer(points, 3); 49834f572ea9SToby Isaac PetscAssertPointer(numCoveringPoints, 4); 49844f572ea9SToby Isaac PetscAssertPointer(coveringPoints, 5); 49856302a7fbSVaclav Hapla PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize)); 49866302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0])); 49876302a7fbSVaclav Hapla PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1])); 4988552f7358SJed Brown /* Copy in cone of first point */ 49899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof)); 49909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off)); 4991ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize]; 4992552f7358SJed Brown /* Check each successive cone */ 4993552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 4994552f7358SJed Brown PetscInt newMeetSize = 0; 4995552f7358SJed Brown 49969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof)); 49979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off)); 4998552f7358SJed Brown for (c = 0; c < dof; ++c) { 4999552f7358SJed Brown const PetscInt point = mesh->cones[off + c]; 5000552f7358SJed Brown 5001552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5002552f7358SJed Brown if (point == meet[i][m]) { 5003552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5004552f7358SJed Brown break; 5005552f7358SJed Brown } 5006552f7358SJed Brown } 5007552f7358SJed Brown } 5008552f7358SJed Brown meetSize = newMeetSize; 5009552f7358SJed Brown i = 1 - i; 5010552f7358SJed Brown } 5011552f7358SJed Brown *numCoveringPoints = meetSize; 5012552f7358SJed Brown *coveringPoints = meet[i]; 50136302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i])); 50143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5015552f7358SJed Brown } 5016552f7358SJed Brown 5017552f7358SJed Brown /*@C 50182c9a7b26SBarry Smith DMPlexRestoreMeet - Restore an array for the meet of the set of points obtained with `DMPlexGetMeet()` 5019552f7358SJed Brown 5020552f7358SJed Brown Not Collective 5021552f7358SJed Brown 5022552f7358SJed Brown Input Parameters: 5023a1cb98faSBarry Smith + dm - The `DMPLEX` object 5024552f7358SJed Brown . numPoints - The number of input points for the meet 5025552f7358SJed Brown - points - The input points 5026552f7358SJed Brown 5027552f7358SJed Brown Output Parameters: 5028552f7358SJed Brown + numCoveredPoints - The number of points in the meet 5029552f7358SJed Brown - coveredPoints - The points in the meet 5030552f7358SJed Brown 5031552f7358SJed Brown Level: intermediate 5032552f7358SJed Brown 503360225df5SJacob Faibussowitsch Fortran Notes: 503420f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 50353813dfbdSMatthew G Knepley 50361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()` 5037552f7358SJed Brown @*/ 50385d83a8b1SBarry Smith PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5039d71ae5a4SJacob Faibussowitsch { 5040552f7358SJed Brown PetscFunctionBegin; 5041552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50424f572ea9SToby Isaac if (points) PetscAssertPointer(points, 3); 50434f572ea9SToby Isaac if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4); 50444f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 50459566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints)); 5046d7902bd2SMatthew G. Knepley if (numCoveredPoints) *numCoveredPoints = 0; 50473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5048552f7358SJed Brown } 5049552f7358SJed Brown 5050552f7358SJed Brown /*@C 5051552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 5052552f7358SJed Brown 5053552f7358SJed Brown Not Collective 5054552f7358SJed Brown 5055552f7358SJed Brown Input Parameters: 5056a1cb98faSBarry Smith + dm - The `DMPLEX` object 5057552f7358SJed Brown . numPoints - The number of input points for the meet 50582c9a7b26SBarry Smith - points - The input points, of length `numPoints` 5059552f7358SJed Brown 5060552f7358SJed Brown Output Parameters: 5061552f7358SJed Brown + numCoveredPoints - The number of points in the meet 50622c9a7b26SBarry Smith - coveredPoints - The points in the meet, of length `numCoveredPoints` 5063552f7358SJed Brown 5064552f7358SJed Brown Level: intermediate 5065552f7358SJed Brown 506660225df5SJacob Faibussowitsch Fortran Notes: 50672c9a7b26SBarry Smith `points` and `coveredPoints` must be declared with 50682c9a7b26SBarry Smith .vb 50692c9a7b26SBarry Smith PetscInt, pointer :: points(:) 50702c9a7b26SBarry Smith PetscInt, pointer :: coveredPoints(:) 50712c9a7b26SBarry Smith .ve 50722c9a7b26SBarry Smith 507320f4b53cSBarry Smith The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array. 50743813dfbdSMatthew G Knepley 50751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()` 5076552f7358SJed Brown @*/ 50775d83a8b1SBarry Smith PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt *coveredPoints[]) 5078d71ae5a4SJacob Faibussowitsch { 5079552f7358SJed Brown PetscInt *offsets, **closures; 5080552f7358SJed Brown PetscInt *meet[2]; 5081552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 508224c766afSToby Isaac PetscInt p, h, c, m, mc; 5083552f7358SJed Brown 5084552f7358SJed Brown PetscFunctionBegin; 5085552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 50864f572ea9SToby Isaac PetscAssertPointer(points, 3); 50874f572ea9SToby Isaac PetscAssertPointer(numCoveredPoints, 4); 50884f572ea9SToby Isaac PetscAssertPointer(coveredPoints, 5); 5089552f7358SJed Brown 50909566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &height)); 50919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &closures)); 50929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 50936302a7fbSVaclav Hapla PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL)); 509424c766afSToby Isaac maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1; 50959566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0])); 50969566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1])); 5097552f7358SJed Brown 5098552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 5099552f7358SJed Brown PetscInt closureSize; 5100552f7358SJed Brown 51019566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p])); 51020d644c17SKarl Rupp 5103552f7358SJed Brown offsets[p * (height + 2) + 0] = 0; 5104552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5105552f7358SJed Brown PetscInt pStart, pEnd, i; 5106552f7358SJed Brown 51079566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 5108552f7358SJed Brown for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) { 5109552f7358SJed Brown if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) { 5110552f7358SJed Brown offsets[p * (height + 2) + h + 1] = i; 5111552f7358SJed Brown break; 5112552f7358SJed Brown } 5113552f7358SJed Brown } 5114552f7358SJed Brown if (i == closureSize) offsets[p * (height + 2) + h + 1] = i; 5115552f7358SJed Brown } 511663a3b9bcSJacob 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); 5117552f7358SJed Brown } 5118552f7358SJed Brown for (h = 0; h < height + 1; ++h) { 5119552f7358SJed Brown PetscInt dof; 5120552f7358SJed Brown 5121552f7358SJed Brown /* Copy in cone of first point */ 5122552f7358SJed Brown dof = offsets[h + 1] - offsets[h]; 5123ad540459SPierre Jolivet for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2]; 5124552f7358SJed Brown /* Check each successive cone */ 5125552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 5126552f7358SJed Brown PetscInt newMeetSize = 0; 5127552f7358SJed Brown 5128552f7358SJed Brown dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h]; 5129552f7358SJed Brown for (c = 0; c < dof; ++c) { 5130552f7358SJed Brown const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2]; 5131552f7358SJed Brown 5132552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 5133552f7358SJed Brown if (point == meet[i][m]) { 5134552f7358SJed Brown meet[1 - i][newMeetSize++] = point; 5135552f7358SJed Brown break; 5136552f7358SJed Brown } 5137552f7358SJed Brown } 5138552f7358SJed Brown } 5139552f7358SJed Brown meetSize = newMeetSize; 5140552f7358SJed Brown i = 1 - i; 5141552f7358SJed Brown } 5142552f7358SJed Brown if (meetSize) break; 5143552f7358SJed Brown } 5144552f7358SJed Brown *numCoveredPoints = meetSize; 5145552f7358SJed Brown *coveredPoints = meet[i]; 514648a46eb9SPierre Jolivet for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p])); 51479566063dSJacob Faibussowitsch PetscCall(PetscFree(closures)); 51489566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets)); 51496302a7fbSVaclav Hapla PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i])); 51503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5151552f7358SJed Brown } 5152552f7358SJed Brown 5153cc4c1da9SBarry Smith /*@ 5154a1cb98faSBarry Smith DMPlexEqual - Determine if two `DM` have the same topology 51554e3744c5SMatthew G. Knepley 51564e3744c5SMatthew G. Knepley Not Collective 51574e3744c5SMatthew G. Knepley 51584e3744c5SMatthew G. Knepley Input Parameters: 5159a1cb98faSBarry Smith + dmA - A `DMPLEX` object 5160a1cb98faSBarry Smith - dmB - A `DMPLEX` object 51614e3744c5SMatthew G. Knepley 51622fe279fdSBarry Smith Output Parameter: 5163a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical 51644e3744c5SMatthew G. Knepley 51654e3744c5SMatthew G. Knepley Level: intermediate 51664e3744c5SMatthew G. Knepley 5167a1cb98faSBarry Smith Note: 51683c7db156SBarry Smith We are not solving graph isomorphism, so we do not permute. 51694e3744c5SMatthew G. Knepley 51701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 51714e3744c5SMatthew G. Knepley @*/ 5172d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 5173d71ae5a4SJacob Faibussowitsch { 51744e3744c5SMatthew G. Knepley PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 51754e3744c5SMatthew G. Knepley 51764e3744c5SMatthew G. Knepley PetscFunctionBegin; 51774e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 51784e3744c5SMatthew G. Knepley PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 51794f572ea9SToby Isaac PetscAssertPointer(equal, 3); 51804e3744c5SMatthew G. Knepley 51814e3744c5SMatthew G. Knepley *equal = PETSC_FALSE; 51829566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmA, &depth)); 51839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmB, &depthB)); 51843ba16761SJacob Faibussowitsch if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS); 51859566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd)); 51869566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB)); 51873ba16761SJacob Faibussowitsch if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS); 51884e3744c5SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 51894e3744c5SMatthew G. Knepley const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 51904e3744c5SMatthew G. Knepley PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 51914e3744c5SMatthew G. Knepley 51929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmA, p, &coneSize)); 51939566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmA, p, &cone)); 51949566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt)); 51959566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB)); 51969566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dmB, p, &coneB)); 51979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB)); 51983ba16761SJacob Faibussowitsch if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS); 51994e3744c5SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 52003ba16761SJacob Faibussowitsch if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52013ba16761SJacob Faibussowitsch if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS); 52024e3744c5SMatthew G. Knepley } 52039566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize)); 52049566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmA, p, &support)); 52059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB)); 52069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmB, p, &supportB)); 52073ba16761SJacob Faibussowitsch if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS); 52084e3744c5SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 52093ba16761SJacob Faibussowitsch if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS); 52104e3744c5SMatthew G. Knepley } 52114e3744c5SMatthew G. Knepley } 52124e3744c5SMatthew G. Knepley *equal = PETSC_TRUE; 52133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52144e3744c5SMatthew G. Knepley } 52154e3744c5SMatthew G. Knepley 5216cc4c1da9SBarry Smith /*@ 52177cd05799SMatthew G. Knepley DMPlexGetNumFaceVertices - Returns the number of vertices on a face 52187cd05799SMatthew G. Knepley 52197cd05799SMatthew G. Knepley Not Collective 52207cd05799SMatthew G. Knepley 52217cd05799SMatthew G. Knepley Input Parameters: 5222a1cb98faSBarry Smith + dm - The `DMPLEX` 52237cd05799SMatthew G. Knepley . cellDim - The cell dimension 52247cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell 52257cd05799SMatthew G. Knepley 52262fe279fdSBarry Smith Output Parameter: 52277cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face 52287cd05799SMatthew G. Knepley 52297cd05799SMatthew G. Knepley Level: developer 52307cd05799SMatthew G. Knepley 5231a1cb98faSBarry Smith Note: 52327cd05799SMatthew G. Knepley Of course this can only work for a restricted set of symmetric shapes 52337cd05799SMatthew G. Knepley 52341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 52357cd05799SMatthew G. Knepley @*/ 5236d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 5237d71ae5a4SJacob Faibussowitsch { 523882f516ccSBarry Smith MPI_Comm comm; 5239552f7358SJed Brown 5240552f7358SJed Brown PetscFunctionBegin; 52419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 52424f572ea9SToby Isaac PetscAssertPointer(numFaceVertices, 4); 5243552f7358SJed Brown switch (cellDim) { 5244d71ae5a4SJacob Faibussowitsch case 0: 5245d71ae5a4SJacob Faibussowitsch *numFaceVertices = 0; 5246d71ae5a4SJacob Faibussowitsch break; 5247d71ae5a4SJacob Faibussowitsch case 1: 5248d71ae5a4SJacob Faibussowitsch *numFaceVertices = 1; 5249d71ae5a4SJacob Faibussowitsch break; 5250552f7358SJed Brown case 2: 5251552f7358SJed Brown switch (numCorners) { 525219436ca2SJed Brown case 3: /* triangle */ 525319436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5254552f7358SJed Brown break; 525519436ca2SJed Brown case 4: /* quadrilateral */ 525619436ca2SJed Brown *numFaceVertices = 2; /* Edge has 2 vertices */ 5257552f7358SJed Brown break; 525819436ca2SJed Brown case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 525919436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5260552f7358SJed Brown break; 526119436ca2SJed Brown case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 526219436ca2SJed Brown *numFaceVertices = 3; /* Edge has 3 vertices */ 5263552f7358SJed Brown break; 5264d71ae5a4SJacob Faibussowitsch default: 5265d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5266552f7358SJed Brown } 5267552f7358SJed Brown break; 5268552f7358SJed Brown case 3: 5269552f7358SJed Brown switch (numCorners) { 527019436ca2SJed Brown case 4: /* tetradehdron */ 527119436ca2SJed Brown *numFaceVertices = 3; /* Face has 3 vertices */ 5272552f7358SJed Brown break; 527319436ca2SJed Brown case 6: /* tet cohesive cells */ 527419436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5275552f7358SJed Brown break; 527619436ca2SJed Brown case 8: /* hexahedron */ 527719436ca2SJed Brown *numFaceVertices = 4; /* Face has 4 vertices */ 5278552f7358SJed Brown break; 527919436ca2SJed Brown case 9: /* tet cohesive Lagrange cells */ 528019436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5281552f7358SJed Brown break; 528219436ca2SJed Brown case 10: /* quadratic tetrahedron */ 528319436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5284552f7358SJed Brown break; 528519436ca2SJed Brown case 12: /* hex cohesive Lagrange cells */ 528619436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5287552f7358SJed Brown break; 528819436ca2SJed Brown case 18: /* quadratic tet cohesive Lagrange cells */ 528919436ca2SJed Brown *numFaceVertices = 6; /* Face has 6 vertices */ 5290552f7358SJed Brown break; 529119436ca2SJed Brown case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 529219436ca2SJed Brown *numFaceVertices = 9; /* Face has 9 vertices */ 5293552f7358SJed Brown break; 5294d71ae5a4SJacob Faibussowitsch default: 5295d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim); 5296552f7358SJed Brown } 5297552f7358SJed Brown break; 5298d71ae5a4SJacob Faibussowitsch default: 5299d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim); 5300552f7358SJed Brown } 53013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5302552f7358SJed Brown } 5303552f7358SJed Brown 5304552f7358SJed Brown /*@ 5305a1cb98faSBarry Smith DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point 5306552f7358SJed Brown 5307552f7358SJed Brown Not Collective 5308552f7358SJed Brown 5309aa50250dSMatthew G. Knepley Input Parameter: 5310a1cb98faSBarry Smith . dm - The `DMPLEX` object 5311552f7358SJed Brown 5312aa50250dSMatthew G. Knepley Output Parameter: 5313a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth 5314552f7358SJed Brown 5315552f7358SJed Brown Level: developer 5316552f7358SJed Brown 53171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, 5318aa50250dSMatthew G. Knepley @*/ 5319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 5320d71ae5a4SJacob Faibussowitsch { 5321aa50250dSMatthew G. Knepley PetscFunctionBegin; 5322aa50250dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53234f572ea9SToby Isaac PetscAssertPointer(depthLabel, 2); 5324c58f1c22SToby Isaac *depthLabel = dm->depthLabel; 53253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5326aa50250dSMatthew G. Knepley } 5327aa50250dSMatthew G. Knepley 5328aa50250dSMatthew G. Knepley /*@ 5329aa50250dSMatthew G. Knepley DMPlexGetDepth - Get the depth of the DAG representing this mesh 5330aa50250dSMatthew G. Knepley 5331aa50250dSMatthew G. Knepley Not Collective 5332aa50250dSMatthew G. Knepley 5333aa50250dSMatthew G. Knepley Input Parameter: 5334a1cb98faSBarry Smith . dm - The `DMPLEX` object 5335aa50250dSMatthew G. Knepley 5336aa50250dSMatthew G. Knepley Output Parameter: 5337aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG 5338aa50250dSMatthew G. Knepley 5339aa50250dSMatthew G. Knepley Level: developer 5340552f7358SJed Brown 5341b1bb481bSMatthew Knepley Notes: 5342a1cb98faSBarry Smith This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`. 5343a1cb98faSBarry Smith 5344a1cb98faSBarry Smith The point depth is described more in detail in `DMPlexGetDepthStratum()`. 5345a1cb98faSBarry Smith 5346dc287ab2SVaclav Hapla An empty mesh gives -1. 5347b1bb481bSMatthew Knepley 53481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()` 5349552f7358SJed Brown @*/ 5350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 5351d71ae5a4SJacob Faibussowitsch { 53529f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5353aa50250dSMatthew G. Knepley DMLabel label; 5354452349dbSMatthew G. Knepley PetscInt d = -1; 5355552f7358SJed Brown 5356552f7358SJed Brown PetscFunctionBegin; 5357552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 53584f572ea9SToby Isaac PetscAssertPointer(depth, 2); 53599f4ada15SMatthew G. Knepley if (mesh->tr) { 53609f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepth(mesh->tr, depth)); 53619f4ada15SMatthew G. Knepley } else { 53629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 5363452349dbSMatthew G. Knepley // Allow missing depths 5364452349dbSMatthew G. Knepley if (label) PetscCall(DMLabelGetValueBounds(label, NULL, &d)); 5365452349dbSMatthew G. Knepley *depth = d; 53669f4ada15SMatthew G. Knepley } 53673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5368552f7358SJed Brown } 5369552f7358SJed Brown 5370552f7358SJed Brown /*@ 537120f4b53cSBarry Smith DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth. 5372552f7358SJed Brown 5373552f7358SJed Brown Not Collective 5374552f7358SJed Brown 5375552f7358SJed Brown Input Parameters: 5376a1cb98faSBarry Smith + dm - The `DMPLEX` object 5377570fa34dSVaclav Hapla - depth - The requested depth 5378552f7358SJed Brown 5379552f7358SJed Brown Output Parameters: 538020f4b53cSBarry Smith + start - The first point at this `depth` 538120f4b53cSBarry Smith - end - One beyond the last point at this `depth` 5382552f7358SJed Brown 5383552f7358SJed Brown Level: developer 5384552f7358SJed Brown 5385a1cb98faSBarry Smith Notes: 5386a1cb98faSBarry Smith Depth indexing is related to topological dimension. Depth stratum 0 contains the lowest topological dimension points, 5387a1cb98faSBarry Smith often "vertices". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next 5388a1cb98faSBarry Smith higher dimension, e.g., "edges". 5389a1cb98faSBarry Smith 53902827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()` 5391552f7358SJed Brown @*/ 5392d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) 5393d71ae5a4SJacob Faibussowitsch { 53949f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5395aa50250dSMatthew G. Knepley DMLabel label; 539663d1a920SMatthew G. Knepley PetscInt pStart, pEnd; 5397552f7358SJed Brown 5398552f7358SJed Brown PetscFunctionBegin; 5399552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54009371c9d4SSatish Balay if (start) { 54014f572ea9SToby Isaac PetscAssertPointer(start, 3); 54029371c9d4SSatish Balay *start = 0; 54039371c9d4SSatish Balay } 54049371c9d4SSatish Balay if (end) { 54054f572ea9SToby Isaac PetscAssertPointer(end, 4); 54069371c9d4SSatish Balay *end = 0; 54079371c9d4SSatish Balay } 54089566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 54093ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5410570fa34dSVaclav Hapla if (depth < 0) { 541163d1a920SMatthew G. Knepley if (start) *start = pStart; 541263d1a920SMatthew G. Knepley if (end) *end = pEnd; 54133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5414552f7358SJed Brown } 54159f4ada15SMatthew G. Knepley if (mesh->tr) { 54169f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end)); 54179f4ada15SMatthew G. Knepley } else { 54189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 541928b400f6SJacob Faibussowitsch PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 5420570fa34dSVaclav Hapla PetscCall(DMLabelGetStratumBounds(label, depth, start, end)); 54219f4ada15SMatthew G. Knepley } 54223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5423552f7358SJed Brown } 5424552f7358SJed Brown 5425552f7358SJed Brown /*@ 542620f4b53cSBarry Smith DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height. 5427552f7358SJed Brown 5428552f7358SJed Brown Not Collective 5429552f7358SJed Brown 5430552f7358SJed Brown Input Parameters: 5431a1cb98faSBarry Smith + dm - The `DMPLEX` object 5432570fa34dSVaclav Hapla - height - The requested height 5433552f7358SJed Brown 5434552f7358SJed Brown Output Parameters: 543520f4b53cSBarry Smith + start - The first point at this `height` 543620f4b53cSBarry Smith - end - One beyond the last point at this `height` 5437552f7358SJed Brown 5438552f7358SJed Brown Level: developer 5439552f7358SJed Brown 5440a1cb98faSBarry Smith Notes: 5441a1cb98faSBarry Smith Height indexing is related to topological codimension. Height stratum 0 contains the highest topological dimension 5442a1cb98faSBarry Smith points, often called "cells" or "elements". If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height 5443a1cb98faSBarry Smith stratum 1 contains the boundary of these "cells", often called "faces" or "facets". 5444a1cb98faSBarry Smith 54452827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5446552f7358SJed Brown @*/ 5447d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) 5448d71ae5a4SJacob Faibussowitsch { 5449aa50250dSMatthew G. Knepley DMLabel label; 545063d1a920SMatthew G. Knepley PetscInt depth, pStart, pEnd; 5451552f7358SJed Brown 5452552f7358SJed Brown PetscFunctionBegin; 5453552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54549371c9d4SSatish Balay if (start) { 54554f572ea9SToby Isaac PetscAssertPointer(start, 3); 54569371c9d4SSatish Balay *start = 0; 54579371c9d4SSatish Balay } 54589371c9d4SSatish Balay if (end) { 54594f572ea9SToby Isaac PetscAssertPointer(end, 4); 54609371c9d4SSatish Balay *end = 0; 54619371c9d4SSatish Balay } 54629566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 54633ba16761SJacob Faibussowitsch if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 5464570fa34dSVaclav Hapla if (height < 0) { 546563d1a920SMatthew G. Knepley if (start) *start = pStart; 546663d1a920SMatthew G. Knepley if (end) *end = pEnd; 54673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5468552f7358SJed Brown } 54699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 547059e4dc13SStefano Zampini if (label) PetscCall(DMLabelGetNumValues(label, &depth)); 547159e4dc13SStefano Zampini else PetscCall(DMGetDimension(dm, &depth)); 547259e4dc13SStefano Zampini PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed"); 547359e4dc13SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end)); 54743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5475552f7358SJed Brown } 5476552f7358SJed Brown 5477ba2698f1SMatthew G. Knepley /*@ 547820f4b53cSBarry Smith DMPlexGetPointDepth - Get the `depth` of a given point 5479ba2698f1SMatthew G. Knepley 5480ba2698f1SMatthew G. Knepley Not Collective 5481ba2698f1SMatthew G. Knepley 5482d8d19677SJose E. Roman Input Parameters: 5483a1cb98faSBarry Smith + dm - The `DMPLEX` object 5484ba2698f1SMatthew G. Knepley - point - The point 5485ba2698f1SMatthew G. Knepley 5486ba2698f1SMatthew G. Knepley Output Parameter: 548720f4b53cSBarry Smith . depth - The depth of the `point` 5488ba2698f1SMatthew G. Knepley 5489ba2698f1SMatthew G. Knepley Level: intermediate 5490ba2698f1SMatthew G. Knepley 54911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()` 5492ba2698f1SMatthew G. Knepley @*/ 5493d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) 5494d71ae5a4SJacob Faibussowitsch { 5495ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5496ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 54974f572ea9SToby Isaac PetscAssertPointer(depth, 3); 54989566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, depth)); 54993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5500ba2698f1SMatthew G. Knepley } 5501ba2698f1SMatthew G. Knepley 5502ba2698f1SMatthew G. Knepley /*@ 550320f4b53cSBarry Smith DMPlexGetPointHeight - Get the `height` of a given point 55040c0a32dcSVaclav Hapla 55050c0a32dcSVaclav Hapla Not Collective 55060c0a32dcSVaclav Hapla 5507d8d19677SJose E. Roman Input Parameters: 5508a1cb98faSBarry Smith + dm - The `DMPLEX` object 55090c0a32dcSVaclav Hapla - point - The point 55100c0a32dcSVaclav Hapla 55110c0a32dcSVaclav Hapla Output Parameter: 551220f4b53cSBarry Smith . height - The height of the `point` 55130c0a32dcSVaclav Hapla 55140c0a32dcSVaclav Hapla Level: intermediate 55150c0a32dcSVaclav Hapla 55161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()` 55170c0a32dcSVaclav Hapla @*/ 5518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) 5519d71ae5a4SJacob Faibussowitsch { 55200c0a32dcSVaclav Hapla PetscInt n, pDepth; 55210c0a32dcSVaclav Hapla 55220c0a32dcSVaclav Hapla PetscFunctionBegin; 55230c0a32dcSVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55244f572ea9SToby Isaac PetscAssertPointer(height, 3); 55259566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(dm->depthLabel, &n)); 55269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth)); 55270c0a32dcSVaclav Hapla *height = n - 1 - pDepth; /* DAG depth is n-1 */ 55283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55290c0a32dcSVaclav Hapla } 55300c0a32dcSVaclav Hapla 55310c0a32dcSVaclav Hapla /*@ 5532a1cb98faSBarry Smith DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell 5533ba2698f1SMatthew G. Knepley 5534ba2698f1SMatthew G. Knepley Not Collective 5535ba2698f1SMatthew G. Knepley 5536ba2698f1SMatthew G. Knepley Input Parameter: 5537a1cb98faSBarry Smith . dm - The `DMPLEX` object 5538ba2698f1SMatthew G. Knepley 5539ba2698f1SMatthew G. Knepley Output Parameter: 5540a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type 5541412e9a14SMatthew G. Knepley 5542ba2698f1SMatthew G. Knepley Level: developer 5543ba2698f1SMatthew G. Knepley 5544a1cb98faSBarry Smith Note: 5545a1cb98faSBarry Smith This function will trigger automatica computation of cell types. This can be disabled by calling 5546a1cb98faSBarry Smith `DMCreateLabel`(dm, "celltype") beforehand. 5547a1cb98faSBarry Smith 55481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()` 5549ba2698f1SMatthew G. Knepley @*/ 5550d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) 5551d71ae5a4SJacob Faibussowitsch { 5552ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5553ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55544f572ea9SToby Isaac PetscAssertPointer(celltypeLabel, 2); 55559566063dSJacob Faibussowitsch if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm)); 5556ba2698f1SMatthew G. Knepley *celltypeLabel = dm->celltypeLabel; 55573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5558ba2698f1SMatthew G. Knepley } 5559ba2698f1SMatthew G. Knepley 5560ba2698f1SMatthew G. Knepley /*@ 5561ba2698f1SMatthew G. Knepley DMPlexGetCellType - Get the polytope type of a given cell 5562ba2698f1SMatthew G. Knepley 5563ba2698f1SMatthew G. Knepley Not Collective 5564ba2698f1SMatthew G. Knepley 5565d8d19677SJose E. Roman Input Parameters: 5566a1cb98faSBarry Smith + dm - The `DMPLEX` object 5567ba2698f1SMatthew G. Knepley - cell - The cell 5568ba2698f1SMatthew G. Knepley 5569ba2698f1SMatthew G. Knepley Output Parameter: 5570ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell 5571ba2698f1SMatthew G. Knepley 5572ba2698f1SMatthew G. Knepley Level: intermediate 5573ba2698f1SMatthew G. Knepley 55741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()` 5575ba2698f1SMatthew G. Knepley @*/ 5576d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) 5577d71ae5a4SJacob Faibussowitsch { 55789f4ada15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5579ba2698f1SMatthew G. Knepley DMLabel label; 5580ba2698f1SMatthew G. Knepley PetscInt ct; 5581ba2698f1SMatthew G. Knepley 5582ba2698f1SMatthew G. Knepley PetscFunctionBegin; 5583ba2698f1SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55844f572ea9SToby Isaac PetscAssertPointer(celltype, 3); 55859f4ada15SMatthew G. Knepley if (mesh->tr) { 55869f4ada15SMatthew G. Knepley PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype)); 55879f4ada15SMatthew G. Knepley } else { 558821027e53SStefano Zampini PetscInt pStart, pEnd; 558921027e53SStefano Zampini 559021027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL)); 559121027e53SStefano Zampini if (!mesh->cellTypes) { /* XXX remove? optimize? */ 559221027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd)); 559321027e53SStefano Zampini PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 559421027e53SStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 559521027e53SStefano Zampini for (PetscInt p = pStart; p < pEnd; p++) { 559621027e53SStefano Zampini PetscCall(DMLabelGetValue(label, p, &ct)); 5597*6497c311SBarry Smith mesh->cellTypes[p - pStart].value_as_uint8 = (uint8_t)ct; 559821027e53SStefano Zampini } 559921027e53SStefano Zampini } 560021027e53SStefano Zampini *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8; 560121027e53SStefano Zampini if (PetscDefined(USE_DEBUG)) { 56029566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 56039566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, cell, &ct)); 560463a3b9bcSJacob Faibussowitsch PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell); 5605936381afSPierre Jolivet PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct); 560621027e53SStefano Zampini } 56079f4ada15SMatthew G. Knepley } 56083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5609ba2698f1SMatthew G. Knepley } 5610ba2698f1SMatthew G. Knepley 5611412e9a14SMatthew G. Knepley /*@ 5612412e9a14SMatthew G. Knepley DMPlexSetCellType - Set the polytope type of a given cell 5613412e9a14SMatthew G. Knepley 5614412e9a14SMatthew G. Knepley Not Collective 5615412e9a14SMatthew G. Knepley 5616412e9a14SMatthew G. Knepley Input Parameters: 5617a1cb98faSBarry Smith + dm - The `DMPLEX` object 5618412e9a14SMatthew G. Knepley . cell - The cell 5619412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell 5620412e9a14SMatthew G. Knepley 5621a1cb98faSBarry Smith Level: advanced 5622a1cb98faSBarry Smith 5623a1cb98faSBarry Smith Note: 5624a1cb98faSBarry Smith By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function 5625412e9a14SMatthew G. Knepley is executed. This function will override the computed type. However, if automatic classification will not succeed 5626412e9a14SMatthew G. Knepley and a user wants to manually specify all types, the classification must be disabled by calling 5627db485b19SStefano Zampini DMCreateLabel(dm, "celltype") before getting or setting any cell types. 5628412e9a14SMatthew G. Knepley 56291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()` 5630412e9a14SMatthew G. Knepley @*/ 5631d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) 5632d71ae5a4SJacob Faibussowitsch { 563321027e53SStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 5634412e9a14SMatthew G. Knepley DMLabel label; 563521027e53SStefano Zampini PetscInt pStart, pEnd; 5636412e9a14SMatthew G. Knepley 5637412e9a14SMatthew G. Knepley PetscFunctionBegin; 5638412e9a14SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 563921027e53SStefano Zampini PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd)); 56409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 56419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cell, celltype)); 564221027e53SStefano Zampini if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes)); 5643*6497c311SBarry Smith mesh->cellTypes[cell - pStart].value_as_uint8 = (uint8_t)celltype; 56443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5645412e9a14SMatthew G. Knepley } 5646412e9a14SMatthew G. Knepley 5647d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 5648d71ae5a4SJacob Faibussowitsch { 5649c789d87fSToby Isaac PetscSection section; 56503e922f36SToby Isaac PetscInt maxHeight; 5651dd4c3f67SMatthew G. Knepley const char *prefix; 5652552f7358SJed Brown 5653552f7358SJed Brown PetscFunctionBegin; 56549566063dSJacob Faibussowitsch PetscCall(DMClone(dm, cdm)); 5655dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 5656dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix)); 5657dd4c3f67SMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_")); 56589566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight)); 56599566063dSJacob Faibussowitsch PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight)); 56609566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 56619566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*cdm, section)); 56629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 56638f4c458bSMatthew G. Knepley 56649566063dSJacob Faibussowitsch PetscCall(DMSetNumFields(*cdm, 1)); 56659566063dSJacob Faibussowitsch PetscCall(DMCreateDS(*cdm)); 5666dd4c3f67SMatthew G. Knepley (*cdm)->cloneOpts = PETSC_TRUE; 5667dd4c3f67SMatthew G. Knepley if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm)); 56683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5669552f7358SJed Brown } 5670552f7358SJed Brown 5671d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) 5672d71ae5a4SJacob Faibussowitsch { 56736858538eSMatthew G. Knepley Vec coordsLocal, cellCoordsLocal; 56746858538eSMatthew G. Knepley DM coordsDM, cellCoordsDM; 5675f19dbd58SToby Isaac 5676f19dbd58SToby Isaac PetscFunctionBegin; 5677f19dbd58SToby Isaac *field = NULL; 56789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 56799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &coordsDM)); 56806858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal)); 56816858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM)); 5682f19dbd58SToby Isaac if (coordsLocal && coordsDM) { 56836858538eSMatthew G. Knepley if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field)); 56846858538eSMatthew G. Knepley else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field)); 5685f19dbd58SToby Isaac } 56863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5687f19dbd58SToby Isaac } 5688f19dbd58SToby Isaac 5689cc4c1da9SBarry Smith /*@ 56907cd05799SMatthew G. Knepley DMPlexGetConeSection - Return a section which describes the layout of cone data 56917cd05799SMatthew G. Knepley 56927cd05799SMatthew G. Knepley Not Collective 56937cd05799SMatthew G. Knepley 56942fe279fdSBarry Smith Input Parameter: 5695a1cb98faSBarry Smith . dm - The `DMPLEX` object 56967cd05799SMatthew G. Knepley 56977cd05799SMatthew G. Knepley Output Parameter: 5698a1cb98faSBarry Smith . section - The `PetscSection` object 56997cd05799SMatthew G. Knepley 57007cd05799SMatthew G. Knepley Level: developer 57017cd05799SMatthew G. Knepley 57021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection` 57037cd05799SMatthew G. Knepley @*/ 5704d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 5705d71ae5a4SJacob Faibussowitsch { 5706552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5707552f7358SJed Brown 5708552f7358SJed Brown PetscFunctionBegin; 5709552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5710552f7358SJed Brown if (section) *section = mesh->coneSection; 57113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5712552f7358SJed Brown } 5713552f7358SJed Brown 5714cc4c1da9SBarry Smith /*@ 57157cd05799SMatthew G. Knepley DMPlexGetSupportSection - Return a section which describes the layout of support data 57167cd05799SMatthew G. Knepley 57177cd05799SMatthew G. Knepley Not Collective 57187cd05799SMatthew G. Knepley 57192fe279fdSBarry Smith Input Parameter: 5720a1cb98faSBarry Smith . dm - The `DMPLEX` object 57217cd05799SMatthew G. Knepley 57227cd05799SMatthew G. Knepley Output Parameter: 5723a1cb98faSBarry Smith . section - The `PetscSection` object 57247cd05799SMatthew G. Knepley 57257cd05799SMatthew G. Knepley Level: developer 57267cd05799SMatthew G. Knepley 57271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection` 57287cd05799SMatthew G. Knepley @*/ 5729d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 5730d71ae5a4SJacob Faibussowitsch { 57318cb4d582SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57328cb4d582SMatthew G. Knepley 57338cb4d582SMatthew G. Knepley PetscFunctionBegin; 57348cb4d582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57358cb4d582SMatthew G. Knepley if (section) *section = mesh->supportSection; 57363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 57378cb4d582SMatthew G. Knepley } 57388cb4d582SMatthew G. Knepley 57397cd05799SMatthew G. Knepley /*@C 57407cd05799SMatthew G. Knepley DMPlexGetCones - Return cone data 57417cd05799SMatthew G. Knepley 57427cd05799SMatthew G. Knepley Not Collective 57437cd05799SMatthew G. Knepley 57442fe279fdSBarry Smith Input Parameter: 5745a1cb98faSBarry Smith . dm - The `DMPLEX` object 57467cd05799SMatthew G. Knepley 57477cd05799SMatthew G. Knepley Output Parameter: 57487cd05799SMatthew G. Knepley . cones - The cone for each point 57497cd05799SMatthew G. Knepley 57507cd05799SMatthew G. Knepley Level: developer 57517cd05799SMatthew G. Knepley 57521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()` 57537cd05799SMatthew G. Knepley @*/ 5754d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 5755d71ae5a4SJacob Faibussowitsch { 5756552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5757552f7358SJed Brown 5758552f7358SJed Brown PetscFunctionBegin; 5759552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5760552f7358SJed Brown if (cones) *cones = mesh->cones; 57613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5762552f7358SJed Brown } 5763552f7358SJed Brown 57647cd05799SMatthew G. Knepley /*@C 57657cd05799SMatthew G. Knepley DMPlexGetConeOrientations - Return cone orientation data 57667cd05799SMatthew G. Knepley 57677cd05799SMatthew G. Knepley Not Collective 57687cd05799SMatthew G. Knepley 57692fe279fdSBarry Smith Input Parameter: 5770a1cb98faSBarry Smith . dm - The `DMPLEX` object 57717cd05799SMatthew G. Knepley 57727cd05799SMatthew G. Knepley Output Parameter: 5773b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points 57747cd05799SMatthew G. Knepley 57757cd05799SMatthew G. Knepley Level: developer 57767cd05799SMatthew G. Knepley 5777b5a892a1SMatthew G. Knepley Notes: 57782c9a7b26SBarry Smith The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points 57792c9a7b26SBarry Smith as returned by `DMPlexGetConeOrientation()`. 5780b5a892a1SMatthew G. Knepley 5781a1cb98faSBarry Smith The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`. 5782b5a892a1SMatthew G. Knepley 57831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection` 57847cd05799SMatthew G. Knepley @*/ 5785d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 5786d71ae5a4SJacob Faibussowitsch { 5787552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 5788552f7358SJed Brown 5789552f7358SJed Brown PetscFunctionBegin; 5790552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5791552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 57923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5793552f7358SJed Brown } 5794552f7358SJed Brown 57954ee01570SBarry Smith /* FEM Support */ 5796552f7358SJed Brown 5797d2b2dc1eSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 5798d2b2dc1eSMatthew G. Knepley { 5799d2b2dc1eSMatthew G. Knepley PetscInt depth; 5800d2b2dc1eSMatthew G. Knepley 5801d2b2dc1eSMatthew G. Knepley PetscFunctionBegin; 5802d2b2dc1eSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 5803d2b2dc1eSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth, cellIS)); 5804d2b2dc1eSMatthew G. Knepley if (!*cellIS) PetscCall(DMGetStratumIS(plex, "depth", depth, cellIS)); 5805d2b2dc1eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5806d2b2dc1eSMatthew G. Knepley } 5807d2b2dc1eSMatthew G. Knepley 58085962854dSMatthew G. Knepley PetscErrorCode DMPlexGetAllFaces_Internal(DM plex, IS *faceIS) 58095962854dSMatthew G. Knepley { 58105962854dSMatthew G. Knepley PetscInt depth; 58115962854dSMatthew G. Knepley 58125962854dSMatthew G. Knepley PetscFunctionBegin; 58135962854dSMatthew G. Knepley PetscCall(DMPlexGetDepth(plex, &depth)); 58145962854dSMatthew G. Knepley PetscCall(DMGetStratumIS(plex, "dim", depth - 1, faceIS)); 58155962854dSMatthew G. Knepley if (!*faceIS) PetscCall(DMGetStratumIS(plex, "depth", depth - 1, faceIS)); 58165962854dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 58175962854dSMatthew G. Knepley } 58185962854dSMatthew G. Knepley 58199e8305c2SJed Brown /* 58209e8305c2SJed Brown Returns number of components and tensor degree for the field. For interpolated meshes, line should be a point 58219e8305c2SJed Brown representing a line in the section. 58229e8305c2SJed Brown */ 58235f82726aSMatthew G. Knepley static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(DM dm, PetscSection section, PetscInt field, PetscInt line, PetscInt *Nc, PetscInt *k, PetscBool *continuous, PetscBool *tensor) 5824d71ae5a4SJacob Faibussowitsch { 5825e327e467SRezgar Shakeri PetscObject obj; 5826e327e467SRezgar Shakeri PetscClassId id; 5827e327e467SRezgar Shakeri PetscFE fe = NULL; 5828e327e467SRezgar Shakeri 58299e8305c2SJed Brown PetscFunctionBeginHot; 58309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, field, Nc)); 5831e327e467SRezgar Shakeri PetscCall(DMGetField(dm, field, NULL, &obj)); 5832e327e467SRezgar Shakeri PetscCall(PetscObjectGetClassId(obj, &id)); 5833e327e467SRezgar Shakeri if (id == PETSCFE_CLASSID) fe = (PetscFE)obj; 5834e327e467SRezgar Shakeri 5835e327e467SRezgar Shakeri if (!fe) { 5836e327e467SRezgar Shakeri /* Assume the full interpolated mesh is in the chart; lines in particular */ 58379e8305c2SJed Brown /* An order k SEM disc has k-1 dofs on an edge */ 58389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, line, field, k)); 58399e8305c2SJed Brown *k = *k / *Nc + 1; 5840e327e467SRezgar Shakeri } else { 5841e327e467SRezgar Shakeri PetscInt dual_space_size, dim; 58425f82726aSMatthew G. Knepley PetscDualSpace dsp; 58435f82726aSMatthew G. Knepley 5844e327e467SRezgar Shakeri PetscCall(DMGetDimension(dm, &dim)); 58455f82726aSMatthew G. Knepley PetscCall(PetscFEGetDualSpace(fe, &dsp)); 58465f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceGetDimension(dsp, &dual_space_size)); 5847e327e467SRezgar Shakeri *k = (PetscInt)PetscCeilReal(PetscPowReal(dual_space_size / *Nc, 1.0 / dim)) - 1; 58485f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetContinuity(dsp, continuous)); 58495f82726aSMatthew G. Knepley PetscCall(PetscDualSpaceLagrangeGetTensor(dsp, tensor)); 58505f82726aSMatthew G. Knepley } 58515f82726aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 58525f82726aSMatthew G. Knepley } 58535f82726aSMatthew G. Knepley 58545f82726aSMatthew G. Knepley static PetscErrorCode GetFieldSize_Private(PetscInt dim, PetscInt k, PetscBool tensor, PetscInt *dof) 58555f82726aSMatthew G. Knepley { 58565f82726aSMatthew G. Knepley PetscFunctionBeginHot; 58575f82726aSMatthew G. Knepley if (tensor) { 58585f82726aSMatthew G. Knepley *dof = PetscPowInt(k + 1, dim); 58595f82726aSMatthew G. Knepley } else { 58605f82726aSMatthew G. Knepley switch (dim) { 58615f82726aSMatthew G. Knepley case 1: 58625f82726aSMatthew G. Knepley *dof = k + 1; 58635f82726aSMatthew G. Knepley break; 58645f82726aSMatthew G. Knepley case 2: 58655f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2)) / 2; 58665f82726aSMatthew G. Knepley break; 58675f82726aSMatthew G. Knepley case 3: 58685f82726aSMatthew G. Knepley *dof = ((k + 1) * (k + 2) * (k + 3)) / 6; 58695f82726aSMatthew G. Knepley break; 58705f82726aSMatthew G. Knepley default: 58715f82726aSMatthew G. Knepley *dof = 0; 58725f82726aSMatthew G. Knepley } 58739e8305c2SJed Brown } 58743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 58759e8305c2SJed Brown } 58769e8305c2SJed Brown 5877a4355906SMatthew Knepley /*@ 5878bc1eb3faSJed Brown DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a 5879bc1eb3faSJed Brown lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the 588020f4b53cSBarry Smith section provided (or the section of the `DM`). 5881a4355906SMatthew Knepley 5882a4355906SMatthew Knepley Input Parameters: 588320f4b53cSBarry Smith + dm - The `DM` 588420f4b53cSBarry Smith . point - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE` 588520f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section 5886a4355906SMatthew Knepley 5887bc1eb3faSJed Brown Example: 5888bc1eb3faSJed Brown A typical interpolated single-quad mesh might order points as 5889bc1eb3faSJed Brown .vb 5890bc1eb3faSJed Brown [c0, v1, v2, v3, v4, e5, e6, e7, e8] 5891bc1eb3faSJed Brown 5892bc1eb3faSJed Brown v4 -- e6 -- v3 5893bc1eb3faSJed Brown | | 5894bc1eb3faSJed Brown e7 c0 e8 5895bc1eb3faSJed Brown | | 5896bc1eb3faSJed Brown v1 -- e5 -- v2 5897bc1eb3faSJed Brown .ve 5898bc1eb3faSJed Brown 5899bc1eb3faSJed Brown (There is no significance to the ordering described here.) The default section for a Q3 quad might typically assign 5900bc1eb3faSJed Brown dofs in the order of points, e.g., 5901bc1eb3faSJed Brown .vb 5902bc1eb3faSJed Brown c0 -> [0,1,2,3] 5903bc1eb3faSJed Brown v1 -> [4] 5904bc1eb3faSJed Brown ... 5905bc1eb3faSJed Brown e5 -> [8, 9] 5906bc1eb3faSJed Brown .ve 5907bc1eb3faSJed Brown 5908bc1eb3faSJed Brown which corresponds to the dofs 5909bc1eb3faSJed Brown .vb 5910bc1eb3faSJed Brown 6 10 11 7 5911bc1eb3faSJed Brown 13 2 3 15 5912bc1eb3faSJed Brown 12 0 1 14 5913bc1eb3faSJed Brown 4 8 9 5 5914bc1eb3faSJed Brown .ve 5915bc1eb3faSJed Brown 5916bc1eb3faSJed Brown The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering 5917bc1eb3faSJed Brown .vb 5918bc1eb3faSJed Brown 0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6 5919bc1eb3faSJed Brown .ve 5920bc1eb3faSJed Brown 5921bc1eb3faSJed Brown After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically, 5922bc1eb3faSJed Brown .vb 5923bc1eb3faSJed Brown 4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7 5924bc1eb3faSJed Brown .ve 5925bc1eb3faSJed Brown 5926a4355906SMatthew Knepley Level: developer 5927a4355906SMatthew Knepley 5928da9ac489SAlbert Cowie Notes: 5929a1cb98faSBarry Smith The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial 5930a1cb98faSBarry Smith degree of the basis. 5931a1cb98faSBarry Smith 5932da9ac489SAlbert Cowie This is required to run with libCEED. 5933da9ac489SAlbert Cowie 59341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()` 5935a4355906SMatthew Knepley @*/ 5936d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) 5937d71ae5a4SJacob Faibussowitsch { 59387391a63aSMatthew G. Knepley DMLabel label; 5939bb197d40SJed Brown PetscInt dim, depth = -1, eStart = -1, Nf; 59405f82726aSMatthew G. Knepley PetscBool continuous = PETSC_TRUE, tensor = PETSC_TRUE; 59413194fc30SMatthew G. Knepley 59423194fc30SMatthew G. Knepley PetscFunctionBegin; 59439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 59443ba16761SJacob Faibussowitsch if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS); 5945a433471fSStefano Zampini if (point < 0) { 5946a433471fSStefano Zampini PetscInt sStart, sEnd; 5947a433471fSStefano Zampini 59489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd)); 5949a433471fSStefano Zampini point = sEnd - sStart ? sStart : point; 5950a433471fSStefano Zampini } 59519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &label)); 59529566063dSJacob Faibussowitsch if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth)); 59539566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 59549371c9d4SSatish Balay if (depth == 1) { 59559371c9d4SSatish Balay eStart = point; 59569371c9d4SSatish Balay } else if (depth == dim) { 59577391a63aSMatthew G. Knepley const PetscInt *cone; 59587391a63aSMatthew G. Knepley 59599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 5960d4e6627bSStefano Zampini if (dim == 2) eStart = cone[0]; 5961d4e6627bSStefano Zampini else if (dim == 3) { 5962d4e6627bSStefano Zampini const PetscInt *cone2; 59639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[0], &cone2)); 5964d4e6627bSStefano Zampini eStart = cone2[0]; 596563a3b9bcSJacob 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); 596663a3b9bcSJacob 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); 5967e327e467SRezgar Shakeri 59689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 5969bb197d40SJed Brown for (PetscInt d = 1; d <= dim; d++) { 5970bb197d40SJed Brown PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0; 5971bb197d40SJed Brown PetscInt *perm; 5972bb197d40SJed Brown 59733194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 59745f82726aSMatthew G. Knepley PetscInt dof; 59755f82726aSMatthew G. Knepley 59765f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59775f82726aSMatthew G. Knepley PetscCheck(dim == 1 || tensor || !continuous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Continuous field %" PetscInt_FMT " must have a tensor product discretization", f); 59785f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 59795f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 59805f82726aSMatthew G. Knepley size += dof * Nc; 59813194fc30SMatthew G. Knepley } 59829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &perm)); 59833194fc30SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 5984bb197d40SJed Brown switch (d) { 5985babf31e0SJed Brown case 1: 59865f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 59875f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 5988babf31e0SJed Brown /* 5989babf31e0SJed Brown Original ordering is [ edge of length k-1; vtx0; vtx1 ] 5990babf31e0SJed Brown We want [ vtx0; edge of length k-1; vtx1 ] 5991babf31e0SJed Brown */ 5992e327e467SRezgar Shakeri if (continuous) { 5993babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset; 59949371c9d4SSatish Balay for (i = 0; i < k - 1; i++) 59959371c9d4SSatish Balay for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset; 5996babf31e0SJed Brown for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset; 5997babf31e0SJed Brown foffset = offset; 5998e327e467SRezgar Shakeri } else { 59995f82726aSMatthew G. Knepley PetscInt dof; 60005f82726aSMatthew G. Knepley 60015f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60025f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60035f82726aSMatthew G. Knepley foffset = offset; 6004e327e467SRezgar Shakeri } 6005babf31e0SJed Brown break; 600689eabcffSMatthew G. Knepley case 2: 60073194fc30SMatthew 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} */ 60085f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60095f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 60103194fc30SMatthew G. Knepley /* The SEM order is 60113194fc30SMatthew G. Knepley 60123194fc30SMatthew G. Knepley v_lb, {e_b}, v_rb, 601389eabcffSMatthew G. Knepley e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r, 60143194fc30SMatthew G. Knepley v_lt, reverse {e_t}, v_rt 60153194fc30SMatthew G. Knepley */ 6016e327e467SRezgar Shakeri if (continuous) { 60173194fc30SMatthew G. Knepley const PetscInt of = 0; 60183194fc30SMatthew G. Knepley const PetscInt oeb = of + PetscSqr(k - 1); 60193194fc30SMatthew G. Knepley const PetscInt oer = oeb + (k - 1); 60203194fc30SMatthew G. Knepley const PetscInt oet = oer + (k - 1); 60213194fc30SMatthew G. Knepley const PetscInt oel = oet + (k - 1); 60223194fc30SMatthew G. Knepley const PetscInt ovlb = oel + (k - 1); 60233194fc30SMatthew G. Knepley const PetscInt ovrb = ovlb + 1; 60243194fc30SMatthew G. Knepley const PetscInt ovrt = ovrb + 1; 60253194fc30SMatthew G. Knepley const PetscInt ovlt = ovrt + 1; 60263194fc30SMatthew G. Knepley PetscInt o; 60273194fc30SMatthew G. Knepley 60283194fc30SMatthew G. Knepley /* bottom */ 60293194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset; 60309371c9d4SSatish Balay for (o = oeb; o < oer; ++o) 60319371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60323194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset; 60333194fc30SMatthew G. Knepley /* middle */ 60343194fc30SMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 60353194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset; 60369371c9d4SSatish Balay for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o) 60379371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60383194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset; 60393194fc30SMatthew G. Knepley } 60403194fc30SMatthew G. Knepley /* top */ 60413194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset; 60429371c9d4SSatish Balay for (o = oel - 1; o >= oet; --o) 60439371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 60443194fc30SMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset; 60453194fc30SMatthew G. Knepley foffset = offset; 6046e327e467SRezgar Shakeri } else { 60475f82726aSMatthew G. Knepley PetscInt dof; 60485f82726aSMatthew G. Knepley 60495f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 60505f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 60515f82726aSMatthew G. Knepley foffset = offset; 60523194fc30SMatthew G. Knepley } 605389eabcffSMatthew G. Knepley break; 605489eabcffSMatthew G. Knepley case 3: 605589eabcffSMatthew G. Knepley /* The original hex closure is 605689eabcffSMatthew G. Knepley 605789eabcffSMatthew G. Knepley {c, 605889eabcffSMatthew G. Knepley f_b, f_t, f_f, f_b, f_r, f_l, 605989eabcffSMatthew 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, 606089eabcffSMatthew G. Knepley v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb} 606189eabcffSMatthew G. Knepley */ 60625f82726aSMatthew G. Knepley PetscCall(PetscSectionFieldGetTensorDegree_Private(dm, section, f, eStart, &Nc, &k, &continuous, &tensor)); 60635f82726aSMatthew G. Knepley if (!continuous && d < dim) continue; 606489eabcffSMatthew G. Knepley /* The SEM order is 606589eabcffSMatthew G. Knepley Bottom Slice 606689eabcffSMatthew G. Knepley v_blf, {e^{(k-1)-n}_bf}, v_brf, 606789eabcffSMatthew G. Knepley e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br, 606889eabcffSMatthew G. Knepley v_blb, {e_bb}, v_brb, 606989eabcffSMatthew G. Knepley 607089eabcffSMatthew G. Knepley Middle Slice (j) 607189eabcffSMatthew G. Knepley {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf, 607289eabcffSMatthew G. Knepley f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r, 607389eabcffSMatthew G. Knepley e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb, 607489eabcffSMatthew G. Knepley 607589eabcffSMatthew G. Knepley Top Slice 607689eabcffSMatthew G. Knepley v_tlf, {e_tf}, v_trf, 607789eabcffSMatthew G. Knepley e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr, 607889eabcffSMatthew G. Knepley v_tlb, {e^{(k-1)-n}_tb}, v_trb, 607989eabcffSMatthew G. Knepley */ 6080e327e467SRezgar Shakeri if (continuous) { 608189eabcffSMatthew G. Knepley const PetscInt oc = 0; 608289eabcffSMatthew G. Knepley const PetscInt ofb = oc + PetscSqr(k - 1) * (k - 1); 608389eabcffSMatthew G. Knepley const PetscInt oft = ofb + PetscSqr(k - 1); 608489eabcffSMatthew G. Knepley const PetscInt off = oft + PetscSqr(k - 1); 608589eabcffSMatthew G. Knepley const PetscInt ofk = off + PetscSqr(k - 1); 608689eabcffSMatthew G. Knepley const PetscInt ofr = ofk + PetscSqr(k - 1); 608789eabcffSMatthew G. Knepley const PetscInt ofl = ofr + PetscSqr(k - 1); 608889eabcffSMatthew G. Knepley const PetscInt oebl = ofl + PetscSqr(k - 1); 608989eabcffSMatthew G. Knepley const PetscInt oebb = oebl + (k - 1); 609089eabcffSMatthew G. Knepley const PetscInt oebr = oebb + (k - 1); 609189eabcffSMatthew G. Knepley const PetscInt oebf = oebr + (k - 1); 609289eabcffSMatthew G. Knepley const PetscInt oetf = oebf + (k - 1); 609389eabcffSMatthew G. Knepley const PetscInt oetr = oetf + (k - 1); 609489eabcffSMatthew G. Knepley const PetscInt oetb = oetr + (k - 1); 609589eabcffSMatthew G. Knepley const PetscInt oetl = oetb + (k - 1); 609689eabcffSMatthew G. Knepley const PetscInt oerf = oetl + (k - 1); 609789eabcffSMatthew G. Knepley const PetscInt oelf = oerf + (k - 1); 609889eabcffSMatthew G. Knepley const PetscInt oelb = oelf + (k - 1); 609989eabcffSMatthew G. Knepley const PetscInt oerb = oelb + (k - 1); 610089eabcffSMatthew G. Knepley const PetscInt ovblf = oerb + (k - 1); 610189eabcffSMatthew G. Knepley const PetscInt ovblb = ovblf + 1; 610289eabcffSMatthew G. Knepley const PetscInt ovbrb = ovblb + 1; 610389eabcffSMatthew G. Knepley const PetscInt ovbrf = ovbrb + 1; 610489eabcffSMatthew G. Knepley const PetscInt ovtlf = ovbrf + 1; 610589eabcffSMatthew G. Knepley const PetscInt ovtrf = ovtlf + 1; 610689eabcffSMatthew G. Knepley const PetscInt ovtrb = ovtrf + 1; 610789eabcffSMatthew G. Knepley const PetscInt ovtlb = ovtrb + 1; 610889eabcffSMatthew G. Knepley PetscInt o, n; 610989eabcffSMatthew G. Knepley 611089eabcffSMatthew G. Knepley /* Bottom Slice */ 611189eabcffSMatthew G. Knepley /* bottom */ 611289eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset; 61139371c9d4SSatish Balay for (o = oetf - 1; o >= oebf; --o) 61149371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 611589eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset; 611689eabcffSMatthew G. Knepley /* middle */ 611789eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 611889eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset; 61199371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) { 61209371c9d4SSatish Balay o = ofb + n * (k - 1) + i; 61219371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 61229371c9d4SSatish Balay } 612389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset; 61243194fc30SMatthew G. Knepley } 612589eabcffSMatthew G. Knepley /* top */ 612689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset; 61279371c9d4SSatish Balay for (o = oebb; o < oebr; ++o) 61289371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 612989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset; 613089eabcffSMatthew G. Knepley 613189eabcffSMatthew G. Knepley /* Middle Slice */ 613289eabcffSMatthew G. Knepley for (j = 0; j < k - 1; ++j) { 613389eabcffSMatthew G. Knepley /* bottom */ 613489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset; 61359371c9d4SSatish Balay for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o) 61369371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 613789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset; 613889eabcffSMatthew G. Knepley /* middle */ 613989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 614089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset; 61419371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 61429371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset; 614389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset; 614489eabcffSMatthew G. Knepley } 614589eabcffSMatthew G. Knepley /* top */ 614689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset; 61479371c9d4SSatish Balay for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o) 61489371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 614989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset; 615089eabcffSMatthew G. Knepley } 615189eabcffSMatthew G. Knepley 615289eabcffSMatthew G. Knepley /* Top Slice */ 615389eabcffSMatthew G. Knepley /* bottom */ 615489eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset; 61559371c9d4SSatish Balay for (o = oetf; o < oetr; ++o) 61569371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 615789eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset; 615889eabcffSMatthew G. Knepley /* middle */ 615989eabcffSMatthew G. Knepley for (i = 0; i < k - 1; ++i) { 616089eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset; 61619371c9d4SSatish Balay for (n = 0; n < k - 1; ++n) 61629371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset; 616389eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset; 616489eabcffSMatthew G. Knepley } 616589eabcffSMatthew G. Knepley /* top */ 616689eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset; 61679371c9d4SSatish Balay for (o = oetl - 1; o >= oetb; --o) 61689371c9d4SSatish Balay for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset; 616989eabcffSMatthew G. Knepley for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset; 617089eabcffSMatthew G. Knepley 617189eabcffSMatthew G. Knepley foffset = offset; 6172e327e467SRezgar Shakeri } else { 61735f82726aSMatthew G. Knepley PetscInt dof; 61745f82726aSMatthew G. Knepley 61755f82726aSMatthew G. Knepley PetscCall(GetFieldSize_Private(d, k, tensor, &dof)); 61765f82726aSMatthew G. Knepley for (i = 0; i < dof * Nc; ++i, ++offset) perm[offset] = i + foffset; 61775f82726aSMatthew G. Knepley foffset = offset; 617889eabcffSMatthew G. Knepley } 617989eabcffSMatthew G. Knepley break; 6180d71ae5a4SJacob Faibussowitsch default: 6181d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d); 618289eabcffSMatthew G. Knepley } 618389eabcffSMatthew G. Knepley } 618463a3b9bcSJacob Faibussowitsch PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size); 61853194fc30SMatthew G. Knepley /* Check permutation */ 61863194fc30SMatthew G. Knepley { 61873194fc30SMatthew G. Knepley PetscInt *check; 61883194fc30SMatthew G. Knepley 61899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &check)); 61901dca8a05SBarry Smith for (i = 0; i < size; ++i) { 61911dca8a05SBarry Smith check[i] = -1; 61921dca8a05SBarry 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]); 61931dca8a05SBarry Smith } 61943194fc30SMatthew G. Knepley for (i = 0; i < size; ++i) check[perm[i]] = i; 61951dca8a05SBarry Smith for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i); 61969566063dSJacob Faibussowitsch PetscCall(PetscFree(check)); 61973194fc30SMatthew G. Knepley } 61989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm)); 6199a05c9aa3SJed Brown if (d == dim) { // Add permutation for localized (in case this is a coordinate DM) 6200a05c9aa3SJed Brown PetscInt *loc_perm; 62019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size * 2, &loc_perm)); 6202a05c9aa3SJed Brown for (PetscInt i = 0; i < size; i++) { 6203a05c9aa3SJed Brown loc_perm[i] = perm[i]; 6204a05c9aa3SJed Brown loc_perm[size + i] = size + perm[i]; 6205a05c9aa3SJed Brown } 62069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm)); 6207a05c9aa3SJed Brown } 6208bb197d40SJed Brown } 62093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62103194fc30SMatthew G. Knepley } 62113194fc30SMatthew G. Knepley 6212d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) 6213d71ae5a4SJacob Faibussowitsch { 6214e071409bSToby Isaac PetscDS prob; 6215e071409bSToby Isaac PetscInt depth, Nf, h; 6216e071409bSToby Isaac DMLabel label; 6217e071409bSToby Isaac 6218e071409bSToby Isaac PetscFunctionBeginHot; 62199566063dSJacob Faibussowitsch PetscCall(DMGetDS(dm, &prob)); 6220e071409bSToby Isaac Nf = prob->Nf; 6221e071409bSToby Isaac label = dm->depthLabel; 6222e071409bSToby Isaac *dspace = NULL; 6223e071409bSToby Isaac if (field < Nf) { 6224e071409bSToby Isaac PetscObject disc = prob->disc[field]; 6225e071409bSToby Isaac 6226e071409bSToby Isaac if (disc->classid == PETSCFE_CLASSID) { 6227e071409bSToby Isaac PetscDualSpace dsp; 6228e071409bSToby Isaac 62299566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp)); 62309566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &depth)); 62319566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &h)); 6232e071409bSToby Isaac h = depth - 1 - h; 6233e071409bSToby Isaac if (h) { 62349566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace)); 6235e071409bSToby Isaac } else { 6236e071409bSToby Isaac *dspace = dsp; 6237e071409bSToby Isaac } 6238e071409bSToby Isaac } 6239e071409bSToby Isaac } 62403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6241e071409bSToby Isaac } 6242e071409bSToby Isaac 6243d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6244d71ae5a4SJacob Faibussowitsch { 624528351e22SJed Brown PetscScalar *array; 624628351e22SJed Brown const PetscScalar *vArray; 6247d9917b9dSMatthew G. Knepley const PetscInt *cone, *coneO; 62481a271a75SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 6249552f7358SJed Brown 62501b406b76SMatthew G. Knepley PetscFunctionBeginHot; 62519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 62529566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 62539566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 62549566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 62553f7cbbe7SMatthew G. Knepley if (!values || !*values) { 62569df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 62579df71ca4SMatthew G. Knepley PetscInt dof; 6258d9917b9dSMatthew G. Knepley 62599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62609df71ca4SMatthew G. Knepley size += dof; 62619df71ca4SMatthew G. Knepley } 62629df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 62639df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 62642a3aaacfSMatthew G. Knepley PetscInt dof; 62655a1bb5cfSMatthew G. Knepley 62665a1bb5cfSMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 62679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 62685a1bb5cfSMatthew G. Knepley size += dof; 62695a1bb5cfSMatthew G. Knepley } 62703f7cbbe7SMatthew G. Knepley if (!values) { 62713f7cbbe7SMatthew G. Knepley if (csize) *csize = size; 62723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62733f7cbbe7SMatthew G. Knepley } 62749566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array)); 6275982e9ed1SMatthew G. Knepley } else { 6276982e9ed1SMatthew G. Knepley array = *values; 6277982e9ed1SMatthew G. Knepley } 62789df71ca4SMatthew G. Knepley size = 0; 627928351e22SJed Brown PetscCall(VecGetArrayRead(v, &vArray)); 62809df71ca4SMatthew G. Knepley if ((point >= pStart) && (point < pEnd)) { 62819df71ca4SMatthew G. Knepley PetscInt dof, off, d; 628228351e22SJed Brown const PetscScalar *varr; 6283d9917b9dSMatthew G. Knepley 62849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 62859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 62868e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 6287ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 62889df71ca4SMatthew G. Knepley size += dof; 62899df71ca4SMatthew G. Knepley } 62909df71ca4SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 62919df71ca4SMatthew G. Knepley const PetscInt cp = cone[p]; 62929df71ca4SMatthew G. Knepley PetscInt o = coneO[p]; 62935a1bb5cfSMatthew G. Knepley PetscInt dof, off, d; 629428351e22SJed Brown const PetscScalar *varr; 62955a1bb5cfSMatthew G. Knepley 629652ed52e8SMatthew G. Knepley if ((cp < pStart) || (cp >= pEnd)) continue; 62979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 62989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &off)); 62998e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 63005a1bb5cfSMatthew G. Knepley if (o >= 0) { 6301ad540459SPierre Jolivet for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 63025a1bb5cfSMatthew G. Knepley } else { 6303ad540459SPierre Jolivet for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d]; 63045a1bb5cfSMatthew G. Knepley } 63059df71ca4SMatthew G. Knepley size += dof; 63065a1bb5cfSMatthew G. Knepley } 630728351e22SJed Brown PetscCall(VecRestoreArrayRead(v, &vArray)); 63089df71ca4SMatthew G. Knepley if (!*values) { 63095a1bb5cfSMatthew G. Knepley if (csize) *csize = size; 63105a1bb5cfSMatthew G. Knepley *values = array; 63119df71ca4SMatthew G. Knepley } else { 631263a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 63138c312ff3SMatthew G. Knepley *csize = size; 63149df71ca4SMatthew G. Knepley } 63153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63165a1bb5cfSMatthew G. Knepley } 6317d9917b9dSMatthew G. Knepley 631827f02ce8SMatthew G. Knepley /* Compress out points not in the section */ 6319d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) 6320d71ae5a4SJacob Faibussowitsch { 632127f02ce8SMatthew G. Knepley const PetscInt np = *numPoints; 632227f02ce8SMatthew G. Knepley PetscInt pStart, pEnd, p, q; 632327f02ce8SMatthew G. Knepley 63249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 632527f02ce8SMatthew G. Knepley for (p = 0, q = 0; p < np; ++p) { 632627f02ce8SMatthew G. Knepley const PetscInt r = points[p * 2]; 632727f02ce8SMatthew G. Knepley if ((r >= pStart) && (r < pEnd)) { 632827f02ce8SMatthew G. Knepley points[q * 2] = r; 632927f02ce8SMatthew G. Knepley points[q * 2 + 1] = points[p * 2 + 1]; 633027f02ce8SMatthew G. Knepley ++q; 633127f02ce8SMatthew G. Knepley } 633227f02ce8SMatthew G. Knepley } 633327f02ce8SMatthew G. Knepley *numPoints = q; 63343ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 633527f02ce8SMatthew G. Knepley } 633627f02ce8SMatthew G. Knepley 633797529cf3SJed Brown /* Compressed closure does not apply closure permutation */ 633807218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6339d71ae5a4SJacob Faibussowitsch { 634027f02ce8SMatthew G. Knepley const PetscInt *cla = NULL; 6341923c78e0SToby Isaac PetscInt np, *pts = NULL; 6342923c78e0SToby Isaac 6343923c78e0SToby Isaac PetscFunctionBeginHot; 63449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints)); 634507218a29SMatthew G. Knepley if (!ornt && *clPoints) { 6346923c78e0SToby Isaac PetscInt dof, off; 6347923c78e0SToby Isaac 63489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(*clSec, point, &dof)); 63499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(*clSec, point, &off)); 63509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*clPoints, &cla)); 6351923c78e0SToby Isaac np = dof / 2; 63528e3a54c0SPierre Jolivet pts = PetscSafePointerPlusOffset((PetscInt *)cla, off); 635327f02ce8SMatthew G. Knepley } else { 635407218a29SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts)); 63559566063dSJacob Faibussowitsch PetscCall(CompressPoints_Private(section, &np, pts)); 6356923c78e0SToby Isaac } 6357923c78e0SToby Isaac *numPoints = np; 6358923c78e0SToby Isaac *points = pts; 6359923c78e0SToby Isaac *clp = cla; 63603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6361923c78e0SToby Isaac } 6362923c78e0SToby Isaac 6363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) 6364d71ae5a4SJacob Faibussowitsch { 6365923c78e0SToby Isaac PetscFunctionBeginHot; 6366923c78e0SToby Isaac if (!*clPoints) { 63679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points)); 6368923c78e0SToby Isaac } else { 63699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*clPoints, clp)); 6370923c78e0SToby Isaac } 6371923c78e0SToby Isaac *numPoints = 0; 6372923c78e0SToby Isaac *points = NULL; 6373923c78e0SToby Isaac *clSec = NULL; 6374923c78e0SToby Isaac *clPoints = NULL; 6375923c78e0SToby Isaac *clp = NULL; 63763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6377923c78e0SToby Isaac } 6378923c78e0SToby Isaac 6379d71ae5a4SJacob 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[]) 6380d71ae5a4SJacob Faibussowitsch { 63811a271a75SMatthew G. Knepley PetscInt offset = 0, p; 638297e99dd9SToby Isaac const PetscInt **perms = NULL; 638397e99dd9SToby Isaac const PetscScalar **flips = NULL; 63841a271a75SMatthew G. Knepley 63851a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6386fe02ba77SJed Brown *size = 0; 63879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 638897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 638997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 639097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 639197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 63921a271a75SMatthew G. Knepley PetscInt dof, off, d; 63931a271a75SMatthew G. Knepley const PetscScalar *varr; 63941a271a75SMatthew G. Knepley 63959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 63969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 63978e3a54c0SPierre Jolivet varr = PetscSafePointerPlusOffset(vArray, off); 639897e99dd9SToby Isaac if (clperm) { 639997e99dd9SToby Isaac if (perm) { 640097e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d]; 64011a271a75SMatthew G. Knepley } else { 640297e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d]; 640397e99dd9SToby Isaac } 640497e99dd9SToby Isaac if (flip) { 640597e99dd9SToby Isaac for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d]; 640697e99dd9SToby Isaac } 640797e99dd9SToby Isaac } else { 640897e99dd9SToby Isaac if (perm) { 640997e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d]; 641097e99dd9SToby Isaac } else { 641197e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] = varr[d]; 641297e99dd9SToby Isaac } 641397e99dd9SToby Isaac if (flip) { 641497e99dd9SToby Isaac for (d = 0; d < dof; d++) array[offset + d] *= flip[d]; 64151a271a75SMatthew G. Knepley } 64161a271a75SMatthew G. Knepley } 641797e99dd9SToby Isaac offset += dof; 641897e99dd9SToby Isaac } 64199566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 64201a271a75SMatthew G. Knepley *size = offset; 64213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64221a271a75SMatthew G. Knepley } 64231a271a75SMatthew G. Knepley 6424d71ae5a4SJacob 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[]) 6425d71ae5a4SJacob Faibussowitsch { 64261a271a75SMatthew G. Knepley PetscInt offset = 0, f; 64271a271a75SMatthew G. Knepley 64281a271a75SMatthew G. Knepley PetscFunctionBeginHot; 6429fe02ba77SJed Brown *size = 0; 64301a271a75SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 643197e99dd9SToby Isaac PetscInt p; 643297e99dd9SToby Isaac const PetscInt **perms = NULL; 643397e99dd9SToby Isaac const PetscScalar **flips = NULL; 64341a271a75SMatthew G. Knepley 64359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 643697e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 643797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 643897e99dd9SToby Isaac PetscInt fdof, foff, b; 64391a271a75SMatthew G. Knepley const PetscScalar *varr; 644097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 644197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 64421a271a75SMatthew G. Knepley 64439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 64449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 64451a271a75SMatthew G. Knepley varr = &vArray[foff]; 644697e99dd9SToby Isaac if (clperm) { 64479371c9d4SSatish Balay if (perm) { 6448ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b]; 64491a271a75SMatthew G. Knepley } else { 6450ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b]; 64519371c9d4SSatish Balay } 64529371c9d4SSatish Balay if (flip) { 6453ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b]; 64549371c9d4SSatish Balay } 64559371c9d4SSatish Balay } else { 64569371c9d4SSatish Balay if (perm) { 6457ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b]; 64589371c9d4SSatish Balay } else { 6459ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] = varr[b]; 64609371c9d4SSatish Balay } 64619371c9d4SSatish Balay if (flip) { 6462ad540459SPierre Jolivet for (b = 0; b < fdof; b++) array[offset + b] *= flip[b]; 64639371c9d4SSatish Balay } 64641a271a75SMatthew G. Knepley } 646597e99dd9SToby Isaac offset += fdof; 64661a271a75SMatthew G. Knepley } 64679566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 64681a271a75SMatthew G. Knepley } 64691a271a75SMatthew G. Knepley *size = offset; 64703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64711a271a75SMatthew G. Knepley } 64721a271a75SMatthew G. Knepley 6473e8e188d2SZach Atkins PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, PetscBool useClPerm, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[]) 647407218a29SMatthew G. Knepley { 647507218a29SMatthew G. Knepley PetscSection clSection; 647607218a29SMatthew G. Knepley IS clPoints; 647707218a29SMatthew G. Knepley PetscInt *points = NULL; 6478e8e188d2SZach Atkins const PetscInt *clp, *perm = NULL; 647907218a29SMatthew G. Knepley PetscInt depth, numFields, numPoints, asize; 648007218a29SMatthew G. Knepley 648107218a29SMatthew G. Knepley PetscFunctionBeginHot; 648207218a29SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 648307218a29SMatthew G. Knepley if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 648407218a29SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6485e8e188d2SZach Atkins PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 648607218a29SMatthew G. Knepley PetscCall(DMPlexGetDepth(dm, &depth)); 648707218a29SMatthew G. Knepley PetscCall(PetscSectionGetNumFields(section, &numFields)); 648807218a29SMatthew G. Knepley if (depth == 1 && numFields < 2) { 648907218a29SMatthew G. Knepley PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 649007218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 649107218a29SMatthew G. Knepley } 649207218a29SMatthew G. Knepley /* Get points */ 649307218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp)); 649407218a29SMatthew G. Knepley /* Get sizes */ 649507218a29SMatthew G. Knepley asize = 0; 649607218a29SMatthew G. Knepley for (PetscInt p = 0; p < numPoints * 2; p += 2) { 649707218a29SMatthew G. Knepley PetscInt dof; 649807218a29SMatthew G. Knepley PetscCall(PetscSectionGetDof(section, points[p], &dof)); 649907218a29SMatthew G. Knepley asize += dof; 650007218a29SMatthew G. Knepley } 650107218a29SMatthew G. Knepley if (values) { 650207218a29SMatthew G. Knepley const PetscScalar *vArray; 650307218a29SMatthew G. Knepley PetscInt size; 650407218a29SMatthew G. Knepley 650507218a29SMatthew G. Knepley if (*values) { 650607218a29SMatthew 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); 650707218a29SMatthew G. Knepley } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values)); 6508e8e188d2SZach Atkins if (useClPerm) PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm)); 650907218a29SMatthew G. Knepley PetscCall(VecGetArrayRead(v, &vArray)); 651007218a29SMatthew G. Knepley /* Get values */ 651107218a29SMatthew G. Knepley if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values)); 651207218a29SMatthew G. Knepley else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values)); 651307218a29SMatthew 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); 651407218a29SMatthew G. Knepley /* Cleanup array */ 651507218a29SMatthew G. Knepley PetscCall(VecRestoreArrayRead(v, &vArray)); 651607218a29SMatthew G. Knepley } 651707218a29SMatthew G. Knepley if (csize) *csize = asize; 651807218a29SMatthew G. Knepley /* Cleanup points */ 651907218a29SMatthew G. Knepley PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 652007218a29SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 652107218a29SMatthew G. Knepley } 652207218a29SMatthew G. Knepley 6523552f7358SJed Brown /*@C 6524552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 6525552f7358SJed Brown 6526552f7358SJed Brown Not collective 6527552f7358SJed Brown 6528552f7358SJed Brown Input Parameters: 6529a1cb98faSBarry Smith + dm - The `DM` 653020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6531552f7358SJed Brown . v - The local vector 6532a1cb98faSBarry Smith - point - The point in the `DM` 6533552f7358SJed Brown 65346b867d5aSJose E. Roman Input/Output Parameters: 653520f4b53cSBarry Smith + csize - The size of the input values array, or `NULL`; on output the number of values in the closure 65362c9a7b26SBarry Smith - values - An array to use for the values, or *values = `NULL` to have it allocated automatically; 65372c9a7b26SBarry Smith if the user provided `NULL`, it is a borrowed array and should not be freed, use `DMPlexVecRestoreClosure()` to return it 653822c1ee49SMatthew G. Knepley 6539552f7358SJed Brown Level: intermediate 6540552f7358SJed Brown 6541a1cb98faSBarry Smith Notes: 654220f4b53cSBarry Smith `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the 6543a1cb98faSBarry Smith calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat` 6544a1cb98faSBarry Smith assembly function, and a user may already have allocated storage for this operation. 6545a1cb98faSBarry Smith 6546a1cb98faSBarry Smith A typical use could be 6547a1cb98faSBarry Smith .vb 6548a1cb98faSBarry Smith values = NULL; 6549a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6550a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6551a1cb98faSBarry Smith <Compute on closure> 6552a1cb98faSBarry Smith } 6553a1cb98faSBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values)); 6554a1cb98faSBarry Smith .ve 6555a1cb98faSBarry Smith or 6556a1cb98faSBarry Smith .vb 6557a1cb98faSBarry Smith PetscMalloc1(clMaxSize, &values); 6558a1cb98faSBarry Smith for (p = pStart; p < pEnd; ++p) { 6559a1cb98faSBarry Smith clSize = clMaxSize; 6560a1cb98faSBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values)); 6561a1cb98faSBarry Smith for (cl = 0; cl < clSize; ++cl) { 6562a1cb98faSBarry Smith <Compute on closure> 6563a1cb98faSBarry Smith } 6564a1cb98faSBarry Smith } 6565a1cb98faSBarry Smith PetscFree(values); 6566a1cb98faSBarry Smith .ve 6567a1cb98faSBarry Smith 656860225df5SJacob Faibussowitsch Fortran Notes: 65692c9a7b26SBarry Smith The `csize` argument is not present in the Fortran binding. 6570a1cb98faSBarry Smith 6571f13dfd9eSBarry Smith `values` must be declared with 6572f13dfd9eSBarry Smith .vb 6573f13dfd9eSBarry Smith PetscScalar,dimension(:),pointer :: values 6574f13dfd9eSBarry Smith .ve 6575f13dfd9eSBarry Smith and it will be allocated internally by PETSc to hold the values returned 6576f13dfd9eSBarry Smith 65771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6578552f7358SJed Brown @*/ 6579d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6580d71ae5a4SJacob Faibussowitsch { 6581d9917b9dSMatthew G. Knepley PetscFunctionBeginHot; 6582e8e188d2SZach Atkins PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, PETSC_TRUE, v, point, 0, csize, values)); 65833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6584552f7358SJed Brown } 6585552f7358SJed Brown 6586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) 6587d71ae5a4SJacob Faibussowitsch { 6588e5c487bfSMatthew G. Knepley DMLabel depthLabel; 6589e5c487bfSMatthew G. Knepley PetscSection clSection; 6590e5c487bfSMatthew G. Knepley IS clPoints; 6591e5c487bfSMatthew G. Knepley PetscScalar *array; 6592e5c487bfSMatthew G. Knepley const PetscScalar *vArray; 6593e5c487bfSMatthew G. Knepley PetscInt *points = NULL; 6594c459fbc1SJed Brown const PetscInt *clp, *perm = NULL; 6595c459fbc1SJed Brown PetscInt mdepth, numFields, numPoints, Np = 0, p, clsize, size; 6596e5c487bfSMatthew G. Knepley 6597e5c487bfSMatthew G. Knepley PetscFunctionBeginHot; 6598e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 65999566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 6600e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 6601e5c487bfSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 66029566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &mdepth)); 66039566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 66049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 6605e5c487bfSMatthew G. Knepley if (mdepth == 1 && numFields < 2) { 66069566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values)); 66073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6608e5c487bfSMatthew G. Knepley } 6609e5c487bfSMatthew G. Knepley /* Get points */ 661007218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 6611c459fbc1SJed Brown for (clsize = 0, p = 0; p < Np; p++) { 6612c459fbc1SJed Brown PetscInt dof; 66139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 6614c459fbc1SJed Brown clsize += dof; 6615c459fbc1SJed Brown } 66169566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm)); 6617e5c487bfSMatthew G. Knepley /* Filter points */ 6618e5c487bfSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 6619e5c487bfSMatthew G. Knepley PetscInt dep; 6620e5c487bfSMatthew G. Knepley 66219566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depthLabel, points[p], &dep)); 6622e5c487bfSMatthew G. Knepley if (dep != depth) continue; 6623e5c487bfSMatthew G. Knepley points[Np * 2 + 0] = points[p]; 6624e5c487bfSMatthew G. Knepley points[Np * 2 + 1] = points[p + 1]; 6625e5c487bfSMatthew G. Knepley ++Np; 6626e5c487bfSMatthew G. Knepley } 6627e5c487bfSMatthew G. Knepley /* Get array */ 6628e5c487bfSMatthew G. Knepley if (!values || !*values) { 6629e5c487bfSMatthew G. Knepley PetscInt asize = 0, dof; 6630e5c487bfSMatthew G. Knepley 6631e5c487bfSMatthew G. Knepley for (p = 0; p < Np * 2; p += 2) { 66329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 6633e5c487bfSMatthew G. Knepley asize += dof; 6634e5c487bfSMatthew G. Knepley } 6635e5c487bfSMatthew G. Knepley if (!values) { 66369566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6637e5c487bfSMatthew G. Knepley if (csize) *csize = asize; 66383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6639e5c487bfSMatthew G. Knepley } 66409566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array)); 6641e5c487bfSMatthew G. Knepley } else { 6642e5c487bfSMatthew G. Knepley array = *values; 6643e5c487bfSMatthew G. Knepley } 66449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &vArray)); 6645e5c487bfSMatthew G. Knepley /* Get values */ 66469566063dSJacob Faibussowitsch if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array)); 66479566063dSJacob Faibussowitsch else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array)); 6648e5c487bfSMatthew G. Knepley /* Cleanup points */ 66499566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 6650e5c487bfSMatthew G. Knepley /* Cleanup array */ 66519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &vArray)); 6652e5c487bfSMatthew G. Knepley if (!*values) { 6653e5c487bfSMatthew G. Knepley if (csize) *csize = size; 6654e5c487bfSMatthew G. Knepley *values = array; 6655e5c487bfSMatthew G. Knepley } else { 665663a3b9bcSJacob Faibussowitsch PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size); 6657e5c487bfSMatthew G. Knepley *csize = size; 6658e5c487bfSMatthew G. Knepley } 66593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6660e5c487bfSMatthew G. Knepley } 6661e5c487bfSMatthew G. Knepley 6662552f7358SJed Brown /*@C 6663f13dfd9eSBarry Smith DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' obtained with `DMPlexVecGetClosure()` 6664552f7358SJed Brown 6665552f7358SJed Brown Not collective 6666552f7358SJed Brown 6667552f7358SJed Brown Input Parameters: 6668a1cb98faSBarry Smith + dm - The `DM` 666920f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 6670552f7358SJed Brown . v - The local vector 6671a1cb98faSBarry Smith . point - The point in the `DM` 667220f4b53cSBarry Smith . csize - The number of values in the closure, or `NULL` 6673f13dfd9eSBarry Smith - values - The array of values 6674552f7358SJed Brown 6675552f7358SJed Brown Level: intermediate 6676552f7358SJed Brown 6677a1cb98faSBarry Smith Note: 667820f4b53cSBarry Smith The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()` 6679a1cb98faSBarry Smith 6680f13dfd9eSBarry Smith Fortran Note: 668120f4b53cSBarry Smith The `csize` argument is not present in the Fortran binding since it is internal to the array. 6682a1cb98faSBarry Smith 66831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()` 6684552f7358SJed Brown @*/ 6685d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 6686d71ae5a4SJacob Faibussowitsch { 6687552f7358SJed Brown PetscInt size = 0; 6688552f7358SJed Brown 6689552f7358SJed Brown PetscFunctionBegin; 6690552f7358SJed Brown /* Should work without recalculating size */ 66919566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values)); 6692c9fdaa05SMatthew G. Knepley *values = NULL; 66933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6694552f7358SJed Brown } 6695552f7358SJed Brown 6696d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y) 6697d71ae5a4SJacob Faibussowitsch { 66989371c9d4SSatish Balay *x += y; 66999371c9d4SSatish Balay } 6700d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) 6701d71ae5a4SJacob Faibussowitsch { 67029371c9d4SSatish Balay *x = y; 67039371c9d4SSatish Balay } 6704552f7358SJed Brown 6705d71ae5a4SJacob 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[]) 6706d71ae5a4SJacob Faibussowitsch { 6707552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 6708552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6709552f7358SJed Brown PetscScalar *a; 6710552f7358SJed Brown PetscInt off, cind = 0, k; 6711552f7358SJed Brown 6712552f7358SJed Brown PetscFunctionBegin; 67139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 67149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6715552f7358SJed Brown a = &array[off]; 6716552f7358SJed Brown if (!cdof || setBC) { 671797e99dd9SToby Isaac if (clperm) { 67189371c9d4SSatish Balay if (perm) { 6719ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6720552f7358SJed Brown } else { 6721ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 67229371c9d4SSatish Balay } 67239371c9d4SSatish Balay } else { 67249371c9d4SSatish Balay if (perm) { 6725ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 67269371c9d4SSatish Balay } else { 6727ad540459SPierre Jolivet for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 67289371c9d4SSatish Balay } 6729552f7358SJed Brown } 6730552f7358SJed Brown } else { 67319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 673297e99dd9SToby Isaac if (clperm) { 67339371c9d4SSatish Balay if (perm) { 67349371c9d4SSatish Balay for (k = 0; k < dof; ++k) { 67359371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 67369371c9d4SSatish Balay ++cind; 67379371c9d4SSatish Balay continue; 67389371c9d4SSatish Balay } 673997e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 6740552f7358SJed Brown } 6741552f7358SJed Brown } else { 6742552f7358SJed Brown for (k = 0; k < dof; ++k) { 67439371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 67449371c9d4SSatish Balay ++cind; 67459371c9d4SSatish Balay continue; 67469371c9d4SSatish Balay } 674797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 674897e99dd9SToby Isaac } 674997e99dd9SToby Isaac } 675097e99dd9SToby Isaac } else { 675197e99dd9SToby Isaac if (perm) { 675297e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 67539371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 67549371c9d4SSatish Balay ++cind; 67559371c9d4SSatish Balay continue; 67569371c9d4SSatish Balay } 675797e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 675897e99dd9SToby Isaac } 675997e99dd9SToby Isaac } else { 676097e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 67619371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 67629371c9d4SSatish Balay ++cind; 67639371c9d4SSatish Balay continue; 67649371c9d4SSatish Balay } 676597e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 676697e99dd9SToby Isaac } 6767552f7358SJed Brown } 6768552f7358SJed Brown } 6769552f7358SJed Brown } 67703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6771552f7358SJed Brown } 6772552f7358SJed Brown 6773d71ae5a4SJacob 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[]) 6774d71ae5a4SJacob Faibussowitsch { 6775a5e93ea8SMatthew G. Knepley PetscInt cdof; /* The number of constraints on this point */ 6776a5e93ea8SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 6777a5e93ea8SMatthew G. Knepley PetscScalar *a; 6778a5e93ea8SMatthew G. Knepley PetscInt off, cind = 0, k; 6779a5e93ea8SMatthew G. Knepley 6780a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 67819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 67829566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, point, &off)); 6783a5e93ea8SMatthew G. Knepley a = &array[off]; 6784a5e93ea8SMatthew G. Knepley if (cdof) { 67859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 678697e99dd9SToby Isaac if (clperm) { 678797e99dd9SToby Isaac if (perm) { 6788a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6789a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 679097e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.)); 679197e99dd9SToby Isaac cind++; 6792a5e93ea8SMatthew G. Knepley } 6793a5e93ea8SMatthew G. Knepley } 6794a5e93ea8SMatthew G. Knepley } else { 6795a5e93ea8SMatthew G. Knepley for (k = 0; k < dof; ++k) { 6796a5e93ea8SMatthew G. Knepley if ((cind < cdof) && (k == cdofs[cind])) { 679797e99dd9SToby Isaac fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.)); 679897e99dd9SToby Isaac cind++; 679997e99dd9SToby Isaac } 680097e99dd9SToby Isaac } 680197e99dd9SToby Isaac } 680297e99dd9SToby Isaac } else { 680397e99dd9SToby Isaac if (perm) { 680497e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 680597e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 680697e99dd9SToby Isaac fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.)); 680797e99dd9SToby Isaac cind++; 680897e99dd9SToby Isaac } 680997e99dd9SToby Isaac } 681097e99dd9SToby Isaac } else { 681197e99dd9SToby Isaac for (k = 0; k < dof; ++k) { 681297e99dd9SToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 681397e99dd9SToby Isaac fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.)); 681497e99dd9SToby Isaac cind++; 681597e99dd9SToby Isaac } 6816a5e93ea8SMatthew G. Knepley } 6817a5e93ea8SMatthew G. Knepley } 6818a5e93ea8SMatthew G. Knepley } 6819a5e93ea8SMatthew G. Knepley } 68203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6821a5e93ea8SMatthew G. Knepley } 6822a5e93ea8SMatthew G. Knepley 6823d71ae5a4SJacob 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[]) 6824d71ae5a4SJacob Faibussowitsch { 6825552f7358SJed Brown PetscScalar *a; 68261a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 68271a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 682897e99dd9SToby Isaac PetscInt cind = 0, b; 6829552f7358SJed Brown 6830552f7358SJed Brown PetscFunctionBegin; 68319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 68329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 68339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 68341a271a75SMatthew G. Knepley a = &array[foff]; 6835552f7358SJed Brown if (!fcdof || setBC) { 683697e99dd9SToby Isaac if (clperm) { 68379371c9d4SSatish Balay if (perm) { 6838ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6839552f7358SJed Brown } else { 6840ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 68419371c9d4SSatish Balay } 68429371c9d4SSatish Balay } else { 68439371c9d4SSatish Balay if (perm) { 6844ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 68459371c9d4SSatish Balay } else { 6846ad540459SPierre Jolivet for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 68479371c9d4SSatish Balay } 6848552f7358SJed Brown } 6849552f7358SJed Brown } else { 68509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 685197e99dd9SToby Isaac if (clperm) { 685297e99dd9SToby Isaac if (perm) { 685397e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 68549371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68559371c9d4SSatish Balay ++cind; 68569371c9d4SSatish Balay continue; 68579371c9d4SSatish Balay } 685897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6859552f7358SJed Brown } 6860552f7358SJed Brown } else { 686197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 68629371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68639371c9d4SSatish Balay ++cind; 68649371c9d4SSatish Balay continue; 68659371c9d4SSatish Balay } 686697e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 686797e99dd9SToby Isaac } 686897e99dd9SToby Isaac } 686997e99dd9SToby Isaac } else { 687097e99dd9SToby Isaac if (perm) { 687197e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 68729371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68739371c9d4SSatish Balay ++cind; 68749371c9d4SSatish Balay continue; 68759371c9d4SSatish Balay } 687697e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 687797e99dd9SToby Isaac } 687897e99dd9SToby Isaac } else { 687997e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 68809371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 68819371c9d4SSatish Balay ++cind; 68829371c9d4SSatish Balay continue; 68839371c9d4SSatish Balay } 688497e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6885552f7358SJed Brown } 6886552f7358SJed Brown } 6887552f7358SJed Brown } 6888552f7358SJed Brown } 68891a271a75SMatthew G. Knepley *offset += fdof; 68903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6891552f7358SJed Brown } 6892552f7358SJed Brown 6893d71ae5a4SJacob 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[]) 6894d71ae5a4SJacob Faibussowitsch { 6895a5e93ea8SMatthew G. Knepley PetscScalar *a; 68961a271a75SMatthew G. Knepley PetscInt fdof, foff, fcdof, foffset = *offset; 68971a271a75SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 68985da9d227SMatthew G. Knepley PetscInt Nc, cind = 0, ncind = 0, b; 6899ba322698SMatthew G. Knepley PetscBool ncSet, fcSet; 6900a5e93ea8SMatthew G. Knepley 6901a5e93ea8SMatthew G. Knepley PetscFunctionBegin; 69029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &Nc)); 69039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 69049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof)); 69059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff)); 69061a271a75SMatthew G. Knepley a = &array[foff]; 6907a5e93ea8SMatthew G. Knepley if (fcdof) { 6908ba322698SMatthew G. Knepley /* We just override fcdof and fcdofs with Ncc and comps */ 69099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 691097e99dd9SToby Isaac if (clperm) { 691197e99dd9SToby Isaac if (perm) { 6912ba322698SMatthew G. Knepley if (comps) { 6913ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6914ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 69159371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 69169371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 69179371c9d4SSatish Balay ncSet = PETSC_TRUE; 69189371c9d4SSatish Balay } 69199371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 69209371c9d4SSatish Balay ++cind; 69219371c9d4SSatish Balay fcSet = PETSC_TRUE; 69229371c9d4SSatish Balay } 6923ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6924ba322698SMatthew G. Knepley } 6925ba322698SMatthew G. Knepley } else { 692697e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 692797e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 692897e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.)); 6929a5e93ea8SMatthew G. Knepley ++cind; 6930a5e93ea8SMatthew G. Knepley } 6931a5e93ea8SMatthew G. Knepley } 6932ba322698SMatthew G. Knepley } 6933ba322698SMatthew G. Knepley } else { 6934ba322698SMatthew G. Knepley if (comps) { 6935ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6936ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 69379371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 69389371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 69399371c9d4SSatish Balay ncSet = PETSC_TRUE; 69409371c9d4SSatish Balay } 69419371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 69429371c9d4SSatish Balay ++cind; 69439371c9d4SSatish Balay fcSet = PETSC_TRUE; 69449371c9d4SSatish Balay } 6945ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 6946ba322698SMatthew G. Knepley } 6947a5e93ea8SMatthew G. Knepley } else { 694897e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 694997e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 695097e99dd9SToby Isaac fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.)); 695197e99dd9SToby Isaac ++cind; 695297e99dd9SToby Isaac } 695397e99dd9SToby Isaac } 695497e99dd9SToby Isaac } 6955ba322698SMatthew G. Knepley } 695697e99dd9SToby Isaac } else { 695797e99dd9SToby Isaac if (perm) { 6958ba322698SMatthew G. Knepley if (comps) { 6959ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6960ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 69619371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 69629371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 69639371c9d4SSatish Balay ncSet = PETSC_TRUE; 69649371c9d4SSatish Balay } 69659371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 69669371c9d4SSatish Balay ++cind; 69679371c9d4SSatish Balay fcSet = PETSC_TRUE; 69689371c9d4SSatish Balay } 6969ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 6970ba322698SMatthew G. Knepley } 6971ba322698SMatthew G. Knepley } else { 697297e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 697397e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 697497e99dd9SToby Isaac fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.)); 697597e99dd9SToby Isaac ++cind; 697697e99dd9SToby Isaac } 697797e99dd9SToby Isaac } 6978ba322698SMatthew G. Knepley } 6979ba322698SMatthew G. Knepley } else { 6980ba322698SMatthew G. Knepley if (comps) { 6981ba322698SMatthew G. Knepley for (b = 0; b < fdof; b++) { 6982ba322698SMatthew G. Knepley ncSet = fcSet = PETSC_FALSE; 69839371c9d4SSatish Balay if (b % Nc == comps[ncind]) { 69849371c9d4SSatish Balay ncind = (ncind + 1) % Ncc; 69859371c9d4SSatish Balay ncSet = PETSC_TRUE; 69869371c9d4SSatish Balay } 69879371c9d4SSatish Balay if ((cind < fcdof) && (b == fcdofs[cind])) { 69889371c9d4SSatish Balay ++cind; 69899371c9d4SSatish Balay fcSet = PETSC_TRUE; 69909371c9d4SSatish Balay } 6991ad540459SPierre Jolivet if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6992ba322698SMatthew G. Knepley } 699397e99dd9SToby Isaac } else { 699497e99dd9SToby Isaac for (b = 0; b < fdof; b++) { 699597e99dd9SToby Isaac if ((cind < fcdof) && (b == fcdofs[cind])) { 699697e99dd9SToby Isaac fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.)); 6997a5e93ea8SMatthew G. Knepley ++cind; 6998a5e93ea8SMatthew G. Knepley } 6999a5e93ea8SMatthew G. Knepley } 7000a5e93ea8SMatthew G. Knepley } 7001a5e93ea8SMatthew G. Knepley } 7002a5e93ea8SMatthew G. Knepley } 7003ba322698SMatthew G. Knepley } 70041a271a75SMatthew G. Knepley *offset += fdof; 70053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7006a5e93ea8SMatthew G. Knepley } 7007a5e93ea8SMatthew G. Knepley 7008d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7009d71ae5a4SJacob Faibussowitsch { 7010552f7358SJed Brown PetscScalar *array; 70111b406b76SMatthew G. Knepley const PetscInt *cone, *coneO; 70121b406b76SMatthew G. Knepley PetscInt pStart, pEnd, p, numPoints, off, dof; 7013552f7358SJed Brown 70141b406b76SMatthew G. Knepley PetscFunctionBeginHot; 70159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 70169566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &numPoints)); 70179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 70189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &coneO)); 70199566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7020b6ebb6e6SMatthew G. Knepley for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 7021b6ebb6e6SMatthew G. Knepley const PetscInt cp = !p ? point : cone[p - 1]; 7022b6ebb6e6SMatthew G. Knepley const PetscInt o = !p ? 0 : coneO[p - 1]; 7023b6ebb6e6SMatthew G. Knepley 70249371c9d4SSatish Balay if ((cp < pStart) || (cp >= pEnd)) { 70259371c9d4SSatish Balay dof = 0; 70269371c9d4SSatish Balay continue; 70279371c9d4SSatish Balay } 70289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, cp, &dof)); 7029b6ebb6e6SMatthew G. Knepley /* ADD_VALUES */ 7030b6ebb6e6SMatthew G. Knepley { 7031b6ebb6e6SMatthew G. Knepley const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7032b6ebb6e6SMatthew G. Knepley PetscScalar *a; 7033b6ebb6e6SMatthew G. Knepley PetscInt cdof, coff, cind = 0, k; 7034b6ebb6e6SMatthew G. Knepley 70359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof)); 70369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, cp, &coff)); 7037b6ebb6e6SMatthew G. Knepley a = &array[coff]; 7038b6ebb6e6SMatthew G. Knepley if (!cdof) { 7039b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7040ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + k]; 7041b6ebb6e6SMatthew G. Knepley } else { 7042ad540459SPierre Jolivet for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1]; 7043b6ebb6e6SMatthew G. Knepley } 7044b6ebb6e6SMatthew G. Knepley } else { 70459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs)); 7046b6ebb6e6SMatthew G. Knepley if (o >= 0) { 7047b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 70489371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 70499371c9d4SSatish Balay ++cind; 70509371c9d4SSatish Balay continue; 70519371c9d4SSatish Balay } 7052b6ebb6e6SMatthew G. Knepley a[k] += values[off + k]; 7053b6ebb6e6SMatthew G. Knepley } 7054b6ebb6e6SMatthew G. Knepley } else { 7055b6ebb6e6SMatthew G. Knepley for (k = 0; k < dof; ++k) { 70569371c9d4SSatish Balay if ((cind < cdof) && (k == cdofs[cind])) { 70579371c9d4SSatish Balay ++cind; 70589371c9d4SSatish Balay continue; 70599371c9d4SSatish Balay } 7060b6ebb6e6SMatthew G. Knepley a[k] += values[off + dof - k - 1]; 7061b6ebb6e6SMatthew G. Knepley } 7062b6ebb6e6SMatthew G. Knepley } 7063b6ebb6e6SMatthew G. Knepley } 7064b6ebb6e6SMatthew G. Knepley } 7065b6ebb6e6SMatthew G. Knepley } 70669566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 70673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7068b6ebb6e6SMatthew G. Knepley } 70691b406b76SMatthew G. Knepley 70701b406b76SMatthew G. Knepley /*@C 707120f4b53cSBarry Smith DMPlexVecSetClosure - Set an array of the values on the closure of `point` 70721b406b76SMatthew G. Knepley 70731b406b76SMatthew G. Knepley Not collective 70741b406b76SMatthew G. Knepley 70751b406b76SMatthew G. Knepley Input Parameters: 7076a1cb98faSBarry Smith + dm - The `DM` 707720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section 70781b406b76SMatthew G. Knepley . v - The local vector 707920f4b53cSBarry Smith . point - The point in the `DM` 70801b406b76SMatthew G. Knepley . values - The array of values 7081a1cb98faSBarry Smith - mode - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`, 7082a1cb98faSBarry Smith where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions. 70831b406b76SMatthew G. Knepley 70841b406b76SMatthew G. Knepley Level: intermediate 70851b406b76SMatthew G. Knepley 7086f13dfd9eSBarry Smith Note: 7087f13dfd9eSBarry Smith Usually the input arrays were obtained with `DMPlexVecGetClosure()` 7088f13dfd9eSBarry Smith 7089f13dfd9eSBarry Smith Fortran Note: 7090f13dfd9eSBarry Smith `values` must be declared with 7091f13dfd9eSBarry Smith .vb 7092f13dfd9eSBarry Smith PetscScalar,dimension(:),pointer :: values 7093f13dfd9eSBarry Smith .ve 7094f13dfd9eSBarry Smith 70951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()` 70961b406b76SMatthew G. Knepley @*/ 7097d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 7098d71ae5a4SJacob Faibussowitsch { 70991b406b76SMatthew G. Knepley PetscSection clSection; 71001b406b76SMatthew G. Knepley IS clPoints; 71011b406b76SMatthew G. Knepley PetscScalar *array; 71021b406b76SMatthew G. Knepley PetscInt *points = NULL; 710327f02ce8SMatthew G. Knepley const PetscInt *clp, *clperm = NULL; 7104c459fbc1SJed Brown PetscInt depth, numFields, numPoints, p, clsize; 71051b406b76SMatthew G. Knepley 71061a271a75SMatthew G. Knepley PetscFunctionBeginHot; 71071b406b76SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 71089566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 71091a271a75SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 71101a271a75SMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 71119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 71129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 71131b406b76SMatthew G. Knepley if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 71149566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode)); 71153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71161b406b76SMatthew G. Knepley } 71171a271a75SMatthew G. Knepley /* Get points */ 711807218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7119c459fbc1SJed Brown for (clsize = 0, p = 0; p < numPoints; p++) { 7120c459fbc1SJed Brown PetscInt dof; 71219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7122c459fbc1SJed Brown clsize += dof; 7123c459fbc1SJed Brown } 71249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 71251a271a75SMatthew G. Knepley /* Get array */ 71269566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 71271a271a75SMatthew G. Knepley /* Get values */ 7128ef90cfe2SMatthew G. Knepley if (numFields > 0) { 712997e99dd9SToby Isaac PetscInt offset = 0, f; 7130552f7358SJed Brown for (f = 0; f < numFields; ++f) { 713197e99dd9SToby Isaac const PetscInt **perms = NULL; 713297e99dd9SToby Isaac const PetscScalar **flips = NULL; 713397e99dd9SToby Isaac 71349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7135552f7358SJed Brown switch (mode) { 7136552f7358SJed Brown case INSERT_VALUES: 713797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 713897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 713997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 714097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71413ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array)); 71429371c9d4SSatish Balay } 71439371c9d4SSatish Balay break; 7144552f7358SJed Brown case INSERT_ALL_VALUES: 714597e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 714697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 714797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 714897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71493ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array)); 71509371c9d4SSatish Balay } 71519371c9d4SSatish Balay break; 7152a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 715397e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 715497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 715597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 715697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71573ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array)); 71589371c9d4SSatish Balay } 71599371c9d4SSatish Balay break; 7160552f7358SJed Brown case ADD_VALUES: 716197e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 716297e99dd9SToby Isaac const PetscInt point = points[2 * p]; 716397e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 716497e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71653ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array)); 71669371c9d4SSatish Balay } 71679371c9d4SSatish Balay break; 7168552f7358SJed Brown case ADD_ALL_VALUES: 716997e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 717097e99dd9SToby Isaac const PetscInt point = points[2 * p]; 717197e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 717297e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71733ba16761SJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array)); 71749371c9d4SSatish Balay } 71759371c9d4SSatish Balay break; 7176304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 717797e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 717897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 717997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 718097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 71813ba16761SJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array)); 71829371c9d4SSatish Balay } 71839371c9d4SSatish Balay break; 7184d71ae5a4SJacob Faibussowitsch default: 7185d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7186552f7358SJed Brown } 71879566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 71881a271a75SMatthew G. Knepley } 7189552f7358SJed Brown } else { 71901a271a75SMatthew G. Knepley PetscInt dof, off; 719197e99dd9SToby Isaac const PetscInt **perms = NULL; 719297e99dd9SToby Isaac const PetscScalar **flips = NULL; 71931a271a75SMatthew G. Knepley 71949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips)); 7195552f7358SJed Brown switch (mode) { 7196552f7358SJed Brown case INSERT_VALUES: 719797e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 719897e99dd9SToby Isaac const PetscInt point = points[2 * p]; 719997e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720097e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72023ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array)); 72039371c9d4SSatish Balay } 72049371c9d4SSatish Balay break; 7205552f7358SJed Brown case INSERT_ALL_VALUES: 720697e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 720797e99dd9SToby Isaac const PetscInt point = points[2 * p]; 720897e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 720997e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72113ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array)); 72129371c9d4SSatish Balay } 72139371c9d4SSatish Balay break; 7214a5e93ea8SMatthew G. Knepley case INSERT_BC_VALUES: 721597e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 721697e99dd9SToby Isaac const PetscInt point = points[2 * p]; 721797e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 721897e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72203ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array)); 72219371c9d4SSatish Balay } 72229371c9d4SSatish Balay break; 7223552f7358SJed Brown case ADD_VALUES: 722497e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 722597e99dd9SToby Isaac const PetscInt point = points[2 * p]; 722697e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 722797e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72293ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array)); 72309371c9d4SSatish Balay } 72319371c9d4SSatish Balay break; 7232552f7358SJed Brown case ADD_ALL_VALUES: 723397e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 723497e99dd9SToby Isaac const PetscInt point = points[2 * p]; 723597e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 723697e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72383ba16761SJacob Faibussowitsch PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array)); 72399371c9d4SSatish Balay } 72409371c9d4SSatish Balay break; 7241304ab55fSMatthew G. Knepley case ADD_BC_VALUES: 724297e99dd9SToby Isaac for (p = 0, off = 0; p < numPoints; p++, off += dof) { 724397e99dd9SToby Isaac const PetscInt point = points[2 * p]; 724497e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 724597e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 72469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 72473ba16761SJacob Faibussowitsch PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array)); 72489371c9d4SSatish Balay } 72499371c9d4SSatish Balay break; 7250d71ae5a4SJacob Faibussowitsch default: 7251d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7252552f7358SJed Brown } 72539566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips)); 7254552f7358SJed Brown } 72551a271a75SMatthew G. Knepley /* Cleanup points */ 72569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 72571a271a75SMatthew G. Knepley /* Cleanup array */ 72589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 72593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7260552f7358SJed Brown } 7261552f7358SJed Brown 72625f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */ 7263d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) 7264d71ae5a4SJacob Faibussowitsch { 72655f790a90SMatthew G. Knepley PetscFunctionBegin; 726611cc89d2SBarry Smith *contains = PETSC_TRUE; 72675f790a90SMatthew G. Knepley if (label) { 7268d6177c40SToby Isaac PetscInt fdof; 72695f790a90SMatthew G. Knepley 727011cc89d2SBarry Smith PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains)); 727111cc89d2SBarry Smith if (!*contains) { 72729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 72735f790a90SMatthew G. Knepley *offset += fdof; 72743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 72755f790a90SMatthew G. Knepley } 72765f790a90SMatthew G. Knepley } 72773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 72785f790a90SMatthew G. Knepley } 72795f790a90SMatthew G. Knepley 728097529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */ 7281d71ae5a4SJacob 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) 7282d71ae5a4SJacob Faibussowitsch { 7283e07394fbSMatthew G. Knepley PetscSection clSection; 7284e07394fbSMatthew G. Knepley IS clPoints; 7285e07394fbSMatthew G. Knepley PetscScalar *array; 7286e07394fbSMatthew G. Knepley PetscInt *points = NULL; 728797529cf3SJed Brown const PetscInt *clp; 7288e07394fbSMatthew G. Knepley PetscInt numFields, numPoints, p; 728997e99dd9SToby Isaac PetscInt offset = 0, f; 7290e07394fbSMatthew G. Knepley 7291e07394fbSMatthew G. Knepley PetscFunctionBeginHot; 7292e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 72939566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 7294e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 7295e07394fbSMatthew G. Knepley PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 72969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7297e07394fbSMatthew G. Knepley /* Get points */ 729807218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp)); 7299e07394fbSMatthew G. Knepley /* Get array */ 73009566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 7301e07394fbSMatthew G. Knepley /* Get values */ 7302e07394fbSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 730397e99dd9SToby Isaac const PetscInt **perms = NULL; 730497e99dd9SToby Isaac const PetscScalar **flips = NULL; 730511cc89d2SBarry Smith PetscBool contains; 730697e99dd9SToby Isaac 7307e07394fbSMatthew G. Knepley if (!fieldActive[f]) { 7308e07394fbSMatthew G. Knepley for (p = 0; p < numPoints * 2; p += 2) { 7309e07394fbSMatthew G. Knepley PetscInt fdof; 73109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 7311e07394fbSMatthew G. Knepley offset += fdof; 7312e07394fbSMatthew G. Knepley } 7313e07394fbSMatthew G. Knepley continue; 7314e07394fbSMatthew G. Knepley } 73159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7316e07394fbSMatthew G. Knepley switch (mode) { 7317e07394fbSMatthew G. Knepley case INSERT_VALUES: 731897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 731997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 732097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 732197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 732211cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 732311cc89d2SBarry Smith if (!contains) continue; 73249566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array)); 73259371c9d4SSatish Balay } 73269371c9d4SSatish Balay break; 7327e07394fbSMatthew G. Knepley case INSERT_ALL_VALUES: 732897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 732997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 733097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 733197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 733211cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 733311cc89d2SBarry Smith if (!contains) continue; 73349566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array)); 73359371c9d4SSatish Balay } 73369371c9d4SSatish Balay break; 7337e07394fbSMatthew G. Knepley case INSERT_BC_VALUES: 733897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 733997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 734097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 734197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 734211cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 734311cc89d2SBarry Smith if (!contains) continue; 73449566063dSJacob Faibussowitsch PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array)); 73459371c9d4SSatish Balay } 73469371c9d4SSatish Balay break; 7347e07394fbSMatthew G. Knepley case ADD_VALUES: 734897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 734997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 735097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 735197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 735211cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 735311cc89d2SBarry Smith if (!contains) continue; 73549566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array)); 73559371c9d4SSatish Balay } 73569371c9d4SSatish Balay break; 7357e07394fbSMatthew G. Knepley case ADD_ALL_VALUES: 735897e99dd9SToby Isaac for (p = 0; p < numPoints; p++) { 735997e99dd9SToby Isaac const PetscInt point = points[2 * p]; 736097e99dd9SToby Isaac const PetscInt *perm = perms ? perms[p] : NULL; 736197e99dd9SToby Isaac const PetscScalar *flip = flips ? flips[p] : NULL; 736211cc89d2SBarry Smith PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains)); 736311cc89d2SBarry Smith if (!contains) continue; 73649566063dSJacob Faibussowitsch PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array)); 73659371c9d4SSatish Balay } 73669371c9d4SSatish Balay break; 7367d71ae5a4SJacob Faibussowitsch default: 7368d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 7369e07394fbSMatthew G. Knepley } 73709566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips)); 7371e07394fbSMatthew G. Knepley } 7372e07394fbSMatthew G. Knepley /* Cleanup points */ 73739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp)); 7374e07394fbSMatthew G. Knepley /* Cleanup array */ 73759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 73763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7377e07394fbSMatthew G. Knepley } 7378e07394fbSMatthew G. Knepley 7379d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 7380d71ae5a4SJacob Faibussowitsch { 7381552f7358SJed Brown PetscMPIInt rank; 7382552f7358SJed Brown PetscInt i, j; 7383552f7358SJed Brown 7384552f7358SJed Brown PetscFunctionBegin; 73859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 738663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point)); 738763a3b9bcSJacob Faibussowitsch for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i])); 738863a3b9bcSJacob Faibussowitsch for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i])); 7389b0ecff45SMatthew G. Knepley numCIndices = numCIndices ? numCIndices : numRIndices; 73903ba16761SJacob Faibussowitsch if (!values) PetscFunctionReturn(PETSC_SUCCESS); 7391b0ecff45SMatthew G. Knepley for (i = 0; i < numRIndices; i++) { 73929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank)); 7393b0ecff45SMatthew G. Knepley for (j = 0; j < numCIndices; j++) { 7394519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX) 73959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j]))); 7396552f7358SJed Brown #else 73979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j])); 7398552f7358SJed Brown #endif 7399552f7358SJed Brown } 74009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 7401552f7358SJed Brown } 74023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7403552f7358SJed Brown } 7404552f7358SJed Brown 740505586334SMatthew G. Knepley /* 740605586334SMatthew G. Knepley DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array 740705586334SMatthew G. Knepley 740805586334SMatthew G. Knepley Input Parameters: 740905586334SMatthew G. Knepley + section - The section for this data layout 741036fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global? 741105586334SMatthew G. Knepley . point - The point contributing dofs with these indices 741205586334SMatthew G. Knepley . off - The global offset of this point 741305586334SMatthew G. Knepley . loff - The local offset of each field 7414a5b23f4aSJose E. Roman . setBC - The flag determining whether to include indices of boundary values 741505586334SMatthew G. Knepley . perm - A permutation of the dofs on this point, or NULL 741605586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL 741705586334SMatthew G. Knepley 741805586334SMatthew G. Knepley Output Parameter: 741905586334SMatthew G. Knepley . indices - Indices for dofs on this point 742005586334SMatthew G. Knepley 742105586334SMatthew G. Knepley Level: developer 742205586334SMatthew G. Knepley 742305586334SMatthew G. Knepley Note: The indices could be local or global, depending on the value of 'off'. 742405586334SMatthew G. Knepley */ 7425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) 7426d71ae5a4SJacob Faibussowitsch { 7427e6ccafaeSMatthew G Knepley PetscInt dof; /* The number of unknowns on this point */ 7428552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7429552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7430552f7358SJed Brown PetscInt cind = 0, k; 7431552f7358SJed Brown 7432552f7358SJed Brown PetscFunctionBegin; 743308401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 74349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, point, &dof)); 74359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(section, point, &cdof)); 7436552f7358SJed Brown if (!cdof || setBC) { 743705586334SMatthew G. Knepley for (k = 0; k < dof; ++k) { 743805586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 743905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744005586334SMatthew G. Knepley 744105586334SMatthew G. Knepley indices[ind] = off + k; 7442552f7358SJed Brown } 7443552f7358SJed Brown } else { 74449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs)); 74454acb8e1eSToby Isaac for (k = 0; k < dof; ++k) { 744605586334SMatthew G. Knepley const PetscInt preind = perm ? *loff + perm[k] : *loff + k; 744705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 744805586334SMatthew G. Knepley 74494acb8e1eSToby Isaac if ((cind < cdof) && (k == cdofs[cind])) { 74504acb8e1eSToby Isaac /* Insert check for returning constrained indices */ 745105586334SMatthew G. Knepley indices[ind] = -(off + k + 1); 74524acb8e1eSToby Isaac ++cind; 74534acb8e1eSToby Isaac } else { 745436fa2b79SJed Brown indices[ind] = off + k - (islocal ? 0 : cind); 7455552f7358SJed Brown } 7456552f7358SJed Brown } 7457552f7358SJed Brown } 7458e6ccafaeSMatthew G Knepley *loff += dof; 74593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7460552f7358SJed Brown } 7461552f7358SJed Brown 74627e29afd2SMatthew G. Knepley /* 746336fa2b79SJed Brown DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering. 74647e29afd2SMatthew G. Knepley 746536fa2b79SJed Brown Input Parameters: 746636fa2b79SJed Brown + section - a section (global or local) 746720f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global 746836fa2b79SJed Brown . point - point within section 746936fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section 747036fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field 747136fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution. 747236fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field 747336fa2b79SJed Brown . permsoff - offset 747436fa2b79SJed Brown - indperm - index permutation 747536fa2b79SJed Brown 747636fa2b79SJed Brown Output Parameter: 747736fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field 747836fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point 747936fa2b79SJed Brown 748036fa2b79SJed Brown Notes: 748136fa2b79SJed Brown If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs. 748236fa2b79SJed Brown If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position 748336fa2b79SJed Brown in the local vector. 748436fa2b79SJed Brown 748536fa2b79SJed Brown If section is global and setBC=false, the indices for constrained points are negative (and their value is not 748636fa2b79SJed Brown significant). It is invalid to call with a global section and setBC=true. 748736fa2b79SJed Brown 748836fa2b79SJed Brown Developer Note: 748936fa2b79SJed Brown The section is only used for field layout, so islocal is technically a statement about the offset (off). At some point 749036fa2b79SJed Brown in the future, global sections may have fields set, in which case we could pass the global section and obtain the 749136fa2b79SJed Brown offset could be obtained from the section instead of passing it explicitly as we do now. 749236fa2b79SJed Brown 749336fa2b79SJed Brown Example: 749436fa2b79SJed Brown Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}. 749536fa2b79SJed Brown When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE). 749636fa2b79SJed Brown Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices. 749736fa2b79SJed 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. 749836fa2b79SJed Brown 749936fa2b79SJed Brown Level: developer 75007e29afd2SMatthew G. Knepley */ 7501d71ae5a4SJacob 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[]) 7502d71ae5a4SJacob Faibussowitsch { 7503552f7358SJed Brown PetscInt numFields, foff, f; 7504552f7358SJed Brown 7505552f7358SJed Brown PetscFunctionBegin; 750608401ef6SPierre Jolivet PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC"); 75079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7508552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 75094acb8e1eSToby Isaac PetscInt fdof, cfdof; 7510552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 75114acb8e1eSToby Isaac PetscInt cind = 0, b; 75124acb8e1eSToby Isaac const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 7513552f7358SJed Brown 75149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 75159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 7516552f7358SJed Brown if (!cfdof || setBC) { 751705586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 751805586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 751905586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 752005586334SMatthew G. Knepley 752105586334SMatthew G. Knepley indices[ind] = off + foff + b; 752205586334SMatthew G. Knepley } 7523552f7358SJed Brown } else { 75249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 752505586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 752605586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 752705586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 752805586334SMatthew G. Knepley 75294acb8e1eSToby Isaac if ((cind < cfdof) && (b == fcdofs[cind])) { 753005586334SMatthew G. Knepley indices[ind] = -(off + foff + b + 1); 7531552f7358SJed Brown ++cind; 7532552f7358SJed Brown } else { 753336fa2b79SJed Brown indices[ind] = off + foff + b - (islocal ? 0 : cind); 7534552f7358SJed Brown } 7535552f7358SJed Brown } 7536552f7358SJed Brown } 753736fa2b79SJed Brown foff += (setBC || islocal ? fdof : (fdof - cfdof)); 7538552f7358SJed Brown foffs[f] += fdof; 7539552f7358SJed Brown } 75403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7541552f7358SJed Brown } 7542552f7358SJed Brown 75437e29afd2SMatthew G. Knepley /* 75447e29afd2SMatthew G. Knepley This version believes the globalSection offsets for each field, rather than just the point offset 75457e29afd2SMatthew G. Knepley 75467e29afd2SMatthew G. Knepley . foffs - The offset into 'indices' for each field, since it is segregated by field 7547645102dcSJed Brown 7548645102dcSJed Brown Notes: 7549645102dcSJed Brown The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal. 7550645102dcSJed Brown Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists. 75517e29afd2SMatthew G. Knepley */ 7552d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) 7553d71ae5a4SJacob Faibussowitsch { 75547e29afd2SMatthew G. Knepley PetscInt numFields, foff, f; 75557e29afd2SMatthew G. Knepley 75567e29afd2SMatthew G. Knepley PetscFunctionBegin; 75579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 75587e29afd2SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 75597e29afd2SMatthew G. Knepley PetscInt fdof, cfdof; 75607e29afd2SMatthew G. Knepley const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 75617e29afd2SMatthew G. Knepley PetscInt cind = 0, b; 75627e29afd2SMatthew G. Knepley const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL; 75637e29afd2SMatthew G. Knepley 75649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof)); 75659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof)); 75669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff)); 7567645102dcSJed Brown if (!cfdof) { 756805586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 756905586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 757005586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 757105586334SMatthew G. Knepley 757205586334SMatthew G. Knepley indices[ind] = foff + b; 757305586334SMatthew G. Knepley } 75747e29afd2SMatthew G. Knepley } else { 75759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs)); 757605586334SMatthew G. Knepley for (b = 0; b < fdof; ++b) { 757705586334SMatthew G. Knepley const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b; 757805586334SMatthew G. Knepley const PetscInt ind = indperm ? indperm[preind] : preind; 757905586334SMatthew G. Knepley 75807e29afd2SMatthew G. Knepley if ((cind < cfdof) && (b == fcdofs[cind])) { 758105586334SMatthew G. Knepley indices[ind] = -(foff + b + 1); 75827e29afd2SMatthew G. Knepley ++cind; 75837e29afd2SMatthew G. Knepley } else { 758405586334SMatthew G. Knepley indices[ind] = foff + b - cind; 75857e29afd2SMatthew G. Knepley } 75867e29afd2SMatthew G. Knepley } 75877e29afd2SMatthew G. Knepley } 75887e29afd2SMatthew G. Knepley foffs[f] += fdof; 75897e29afd2SMatthew G. Knepley } 75903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75917e29afd2SMatthew G. Knepley } 75927e29afd2SMatthew G. Knepley 7593c789d87fSToby Isaac static PetscErrorCode DMPlexAnchorsGetSubMatIndices(PetscInt nPoints, const PetscInt pnts[], PetscSection section, PetscSection cSec, PetscInt tmpIndices[], PetscInt fieldOffsets[], PetscInt indices[], const PetscInt ***perms) 7594c789d87fSToby Isaac { 7595c789d87fSToby Isaac PetscInt numFields, sStart, sEnd, cStart, cEnd; 7596c789d87fSToby Isaac 7597c789d87fSToby Isaac PetscFunctionBegin; 7598c789d87fSToby Isaac PetscCall(PetscSectionGetNumFields(section, &numFields)); 7599c789d87fSToby Isaac PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7600c789d87fSToby Isaac PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7601c789d87fSToby Isaac for (PetscInt p = 0; p < nPoints; p++) { 7602c789d87fSToby Isaac PetscInt b = pnts[2 * p]; 7603c789d87fSToby Isaac PetscInt bSecDof = 0, bOff; 7604c789d87fSToby Isaac PetscInt cSecDof = 0; 7605c789d87fSToby Isaac PetscSection indices_section; 7606c789d87fSToby Isaac 7607c789d87fSToby Isaac if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7608c789d87fSToby Isaac if (!bSecDof) continue; 7609c789d87fSToby Isaac if (b >= cStart && b < cEnd) PetscCall(PetscSectionGetDof(cSec, b, &cSecDof)); 7610c789d87fSToby Isaac indices_section = cSecDof > 0 ? cSec : section; 7611c789d87fSToby Isaac if (numFields) { 7612c789d87fSToby Isaac PetscInt fStart[32], fEnd[32]; 7613c789d87fSToby Isaac 7614c789d87fSToby Isaac fStart[0] = 0; 7615c789d87fSToby Isaac fEnd[0] = 0; 7616c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7617c789d87fSToby Isaac PetscInt fDof = 0; 7618c789d87fSToby Isaac 7619c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(indices_section, b, f, &fDof)); 7620c789d87fSToby Isaac fStart[f + 1] = fStart[f] + fDof; 7621c789d87fSToby Isaac fEnd[f + 1] = fStart[f + 1]; 7622c789d87fSToby Isaac } 7623c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7624c789d87fSToby Isaac // only apply permutations on one side 7625c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPointFields_Internal(indices_section, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, perms ? p : -1, NULL, tmpIndices)); 7626c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7627c789d87fSToby Isaac for (PetscInt i = fStart[f]; i < fEnd[f]; i++) { indices[fieldOffsets[f]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); } 7628c789d87fSToby Isaac } 7629c789d87fSToby Isaac } else { 7630c789d87fSToby Isaac PetscInt bEnd = 0; 7631c789d87fSToby Isaac 7632c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(indices_section, b, &bOff)); 7633c789d87fSToby Isaac PetscCall(DMPlexGetIndicesPoint_Internal(indices_section, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, tmpIndices)); 7634c789d87fSToby Isaac 7635c789d87fSToby Isaac for (PetscInt i = 0; i < bEnd; i++) indices[fieldOffsets[0]++] = (cSecDof > 0) ? tmpIndices[i] : -(tmpIndices[i] + 1); 7636c789d87fSToby Isaac } 7637c789d87fSToby Isaac } 7638c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7639c789d87fSToby Isaac } 7640c789d87fSToby Isaac 7641c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsGetSubMatModification(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscInt offsets[], PetscScalar *outMat[]) 7642d71ae5a4SJacob Faibussowitsch { 7643d3d1a6afSToby Isaac Mat cMat; 7644d3d1a6afSToby Isaac PetscSection aSec, cSec; 7645d3d1a6afSToby Isaac IS aIS; 7646d3d1a6afSToby Isaac PetscInt aStart = -1, aEnd = -1; 7647a19ea1e9SMatthew G. Knepley PetscInt sStart = -1, sEnd = -1; 7648a19ea1e9SMatthew G. Knepley PetscInt cStart = -1, cEnd = -1; 7649d3d1a6afSToby Isaac const PetscInt *anchors; 7650e969e7a5SJose E. Roman PetscInt numFields, p; 7651d3d1a6afSToby Isaac PetscInt newNumPoints = 0, newNumIndices = 0; 7652c789d87fSToby Isaac PetscInt *newPoints, *indices, *newIndices, *tmpIndices, *tmpNewIndices; 7653c789d87fSToby Isaac PetscInt oldOffsets[32]; 7654d3d1a6afSToby Isaac PetscInt newOffsets[32]; 7655c789d87fSToby Isaac PetscInt oldOffsetsCopy[32]; 7656c789d87fSToby Isaac PetscInt newOffsetsCopy[32]; 7657c789d87fSToby Isaac PetscScalar *modMat = NULL; 7658d3d1a6afSToby Isaac PetscBool anyConstrained = PETSC_FALSE; 7659d3d1a6afSToby Isaac 7660d3d1a6afSToby Isaac PetscFunctionBegin; 7661d3d1a6afSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7662d3d1a6afSToby Isaac PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 76639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 7664d3d1a6afSToby Isaac 76659566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 7666d3d1a6afSToby Isaac /* if there are point-to-point constraints */ 7667d3d1a6afSToby Isaac if (aSec) { 76689566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(newOffsets, 32)); 7669c789d87fSToby Isaac PetscCall(PetscArrayzero(oldOffsets, 32)); 76709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 76719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd)); 7672a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 7673d3d1a6afSToby Isaac /* figure out how many points are going to be in the new element matrix 7674d3d1a6afSToby Isaac * (we allow double counting, because it's all just going to be summed 7675d3d1a6afSToby Isaac * into the global matrix anyway) */ 7676d3d1a6afSToby Isaac for (p = 0; p < 2 * numPoints; p += 2) { 7677d3d1a6afSToby Isaac PetscInt b = points[p]; 7678a19ea1e9SMatthew G. Knepley PetscInt bDof = 0, bSecDof = 0; 7679d3d1a6afSToby Isaac 7680a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7681ad540459SPierre Jolivet if (!bSecDof) continue; 7682c789d87fSToby Isaac 7683c789d87fSToby Isaac for (PetscInt f = 0; f < numFields; f++) { 7684c789d87fSToby Isaac PetscInt fDof = 0; 7685c789d87fSToby Isaac 7686c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7687c789d87fSToby Isaac oldOffsets[f + 1] += fDof; 7688c789d87fSToby Isaac } 768948a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7690d3d1a6afSToby Isaac if (bDof) { 7691d3d1a6afSToby Isaac /* this point is constrained */ 7692d3d1a6afSToby Isaac /* it is going to be replaced by its anchors */ 7693d3d1a6afSToby Isaac PetscInt bOff, q; 7694d3d1a6afSToby Isaac 76959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7696d3d1a6afSToby Isaac for (q = 0; q < bDof; q++) { 7697d3d1a6afSToby Isaac PetscInt a = anchors[bOff + q]; 7698a19ea1e9SMatthew G. Knepley PetscInt aDof = 0; 7699d3d1a6afSToby Isaac 7700a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7701c789d87fSToby Isaac if (aDof) { 7702c789d87fSToby Isaac anyConstrained = PETSC_TRUE; 7703c789d87fSToby Isaac newNumPoints += 1; 7704c789d87fSToby Isaac } 7705d3d1a6afSToby Isaac newNumIndices += aDof; 7706e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7707a19ea1e9SMatthew G. Knepley PetscInt fDof = 0; 7708d3d1a6afSToby Isaac 7709a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof)); 7710d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7711d3d1a6afSToby Isaac } 7712d3d1a6afSToby Isaac } 77139371c9d4SSatish Balay } else { 7714d3d1a6afSToby Isaac /* this point is not constrained */ 7715d3d1a6afSToby Isaac newNumPoints++; 77164b2f2278SToby Isaac newNumIndices += bSecDof; 7717e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) { 7718d3d1a6afSToby Isaac PetscInt fDof; 7719d3d1a6afSToby Isaac 77209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof)); 7721d3d1a6afSToby Isaac newOffsets[f + 1] += fDof; 7722d3d1a6afSToby Isaac } 7723d3d1a6afSToby Isaac } 7724d3d1a6afSToby Isaac } 7725d3d1a6afSToby Isaac } 7726d3d1a6afSToby Isaac if (!anyConstrained) { 772772b80496SMatthew G. Knepley if (outNumPoints) *outNumPoints = 0; 772872b80496SMatthew G. Knepley if (outNumIndices) *outNumIndices = 0; 772972b80496SMatthew G. Knepley if (outPoints) *outPoints = NULL; 7730c789d87fSToby Isaac if (outMat) *outMat = NULL; 77319566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 77323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7733d3d1a6afSToby Isaac } 7734d3d1a6afSToby Isaac 77356ecaa68aSToby Isaac if (outNumPoints) *outNumPoints = newNumPoints; 77366ecaa68aSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 77376ecaa68aSToby Isaac 7738e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f]; 7739e969e7a5SJose E. Roman for (PetscInt f = 0; f < numFields; ++f) oldOffsets[f + 1] += oldOffsets[f]; 7740d3d1a6afSToby Isaac 7741c789d87fSToby Isaac if (!outPoints && !outMat) { 77426ecaa68aSToby Isaac if (offsets) { 7743e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 77446ecaa68aSToby Isaac } 77459566063dSJacob Faibussowitsch if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors)); 77463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77476ecaa68aSToby Isaac } 77486ecaa68aSToby Isaac 77491dca8a05SBarry 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); 7750c789d87fSToby Isaac PetscCheck(!numFields || oldOffsets[numFields] == numIndices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, oldOffsets[numFields], numIndices); 7751d3d1a6afSToby Isaac 77529566063dSJacob Faibussowitsch PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL)); 7753a19ea1e9SMatthew G. Knepley PetscCall(PetscSectionGetChart(cSec, &cStart, &cEnd)); 7754d3d1a6afSToby Isaac 77556ecaa68aSToby Isaac /* output arrays */ 77569566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 7757c789d87fSToby Isaac PetscCall(PetscArrayzero(newPoints, 2 * newNumPoints)); 77586ecaa68aSToby Isaac 7759c789d87fSToby Isaac // get the new Points 7760c789d87fSToby Isaac for (PetscInt p = 0, newP = 0; p < numPoints; p++) { 7761d3d1a6afSToby Isaac PetscInt b = points[2 * p]; 7762c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7763d3d1a6afSToby Isaac 7764a19ea1e9SMatthew G. Knepley if (b >= sStart && b < sEnd) PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7765ad540459SPierre Jolivet if (!bSecDof) continue; 776648a46eb9SPierre Jolivet if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7767d3d1a6afSToby Isaac if (bDof) { 77689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7769c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++) { 7770a19ea1e9SMatthew G. Knepley PetscInt a = anchors[bOff + q], aDof = 0; 7771d3d1a6afSToby Isaac 7772a19ea1e9SMatthew G. Knepley if (a >= sStart && a < sEnd) PetscCall(PetscSectionGetDof(section, a, &aDof)); 7773c789d87fSToby Isaac if (aDof) { 7774c789d87fSToby Isaac newPoints[2 * newP] = a; 7775c789d87fSToby Isaac newPoints[2 * newP + 1] = 0; // orientations are accounted for in constructing the matrix, newly added points are in default orientation 7776d3d1a6afSToby Isaac newP++; 7777d3d1a6afSToby Isaac } 7778d3d1a6afSToby Isaac } 7779d3d1a6afSToby Isaac } else { 7780d3d1a6afSToby Isaac newPoints[2 * newP] = b; 7781c789d87fSToby Isaac newPoints[2 * newP + 1] = points[2 * p + 1]; 7782d3d1a6afSToby Isaac newP++; 7783d3d1a6afSToby Isaac } 7784d3d1a6afSToby Isaac } 7785d3d1a6afSToby Isaac 7786c789d87fSToby Isaac if (outMat) { 7787c789d87fSToby Isaac PetscScalar *tmpMat; 7788c789d87fSToby Isaac PetscCall(PetscArraycpy(oldOffsetsCopy, oldOffsets, 32)); 7789c789d87fSToby Isaac PetscCall(PetscArraycpy(newOffsetsCopy, newOffsets, 32)); 7790c789d87fSToby Isaac 7791c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &indices)); 7792c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7793c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7794c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7795c789d87fSToby Isaac 7796c789d87fSToby Isaac for (PetscInt i = 0; i < numIndices; i++) indices[i] = -1; 7797c789d87fSToby Isaac for (PetscInt i = 0; i < newNumIndices; i++) newIndices[i] = -1; 7798c789d87fSToby Isaac 7799c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(numPoints, points, section, cSec, tmpIndices, oldOffsetsCopy, indices, perms)); 7800c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatIndices(newNumPoints, newPoints, section, section, tmpNewIndices, newOffsetsCopy, newIndices, NULL)); 7801c789d87fSToby Isaac 7802c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7803c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7804c789d87fSToby Isaac PetscCall(PetscArrayzero(modMat, newNumIndices * numIndices)); 7805c789d87fSToby Isaac // for each field, insert the anchor modification into modMat 7806c789d87fSToby Isaac for (PetscInt f = 0; f < PetscMax(1, numFields); f++) { 7807c789d87fSToby Isaac PetscInt fStart = oldOffsets[f]; 7808c789d87fSToby Isaac PetscInt fNewStart = newOffsets[f]; 7809c789d87fSToby Isaac for (PetscInt p = 0, newP = 0, o = fStart, oNew = fNewStart; p < numPoints; p++) { 7810c789d87fSToby Isaac PetscInt b = points[2 * p]; 7811c789d87fSToby Isaac PetscInt bDof = 0, bSecDof = 0, bOff; 7812c789d87fSToby Isaac 7813c789d87fSToby Isaac if (b >= sStart && b < sEnd) { 7814d3d1a6afSToby Isaac if (numFields) { 7815c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, b, f, &bSecDof)); 78169371c9d4SSatish Balay } else { 7817c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, b, &bSecDof)); 7818d3d1a6afSToby Isaac } 7819d3d1a6afSToby Isaac } 7820c789d87fSToby Isaac if (!bSecDof) continue; 7821c789d87fSToby Isaac if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof)); 7822c789d87fSToby Isaac if (bDof) { 7823c789d87fSToby Isaac PetscCall(PetscSectionGetOffset(aSec, b, &bOff)); 7824c789d87fSToby Isaac for (PetscInt q = 0; q < bDof; q++, newP++) { 7825c789d87fSToby Isaac PetscInt a = anchors[bOff + q], aDof = 0; 7826d3d1a6afSToby Isaac 7827c789d87fSToby Isaac if (a >= sStart && a < sEnd) { 7828d3d1a6afSToby Isaac if (numFields) { 7829c789d87fSToby Isaac PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 7830c789d87fSToby Isaac } else { 7831c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, a, &aDof)); 7832d3d1a6afSToby Isaac } 7833d3d1a6afSToby Isaac } 7834c789d87fSToby Isaac if (aDof) { 7835c789d87fSToby Isaac PetscCall(MatGetValues(cMat, bSecDof, &indices[o], aDof, &newIndices[oNew], tmpMat)); 7836c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) { 7837c789d87fSToby Isaac for (PetscInt e = 0; e < aDof; e++) modMat[(o + d) * newNumIndices + oNew + e] = tmpMat[d * aDof + e]; 7838c789d87fSToby Isaac } 7839c789d87fSToby Isaac } 7840c789d87fSToby Isaac oNew += aDof; 7841c789d87fSToby Isaac } 78429371c9d4SSatish Balay } else { 7843c789d87fSToby Isaac // Insert the identity matrix in this block 7844c789d87fSToby Isaac for (PetscInt d = 0; d < bSecDof; d++) modMat[(o + d) * newNumIndices + oNew + d] = 1; 7845c789d87fSToby Isaac oNew += bSecDof; 7846c789d87fSToby Isaac newP++; 7847d3d1a6afSToby Isaac } 7848c789d87fSToby Isaac o += bSecDof; 7849d3d1a6afSToby Isaac } 7850d3d1a6afSToby Isaac } 7851d3d1a6afSToby Isaac 7852c789d87fSToby Isaac *outMat = modMat; 78536ecaa68aSToby Isaac 7854c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &tmpMat)); 7855c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &tmpNewIndices)); 7856c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, newNumIndices, MPIU_INT, &newIndices)); 7857c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &tmpIndices)); 7858c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices, MPIU_INT, &indices)); 7859d3d1a6afSToby Isaac } 78609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 7861d3d1a6afSToby Isaac 7862d3d1a6afSToby Isaac /* output */ 78636ecaa68aSToby Isaac if (outPoints) { 7864d3d1a6afSToby Isaac *outPoints = newPoints; 78659371c9d4SSatish Balay } else { 78669566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints)); 78676ecaa68aSToby Isaac } 7868e969e7a5SJose E. Roman for (PetscInt f = 0; f <= numFields; f++) offsets[f] = newOffsets[f]; 78693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7870d3d1a6afSToby Isaac } 7871d3d1a6afSToby Isaac 7872c789d87fSToby Isaac PETSC_INTERN PetscErrorCode DMPlexAnchorsModifyMat_Internal(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, PetscInt numRows, PetscInt numCols, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyRight, PetscBool multiplyLeft) 7873c789d87fSToby Isaac { 7874c789d87fSToby Isaac PetscScalar *modMat = NULL; 7875c789d87fSToby Isaac PetscInt newNumIndices = -1; 78767cd05799SMatthew G. Knepley 7877c789d87fSToby Isaac PetscFunctionBegin; 7878c789d87fSToby Isaac /* If M is the matrix represented by values, get the matrix C such that we will add M * C (or, if multiplyLeft, C^T * M * C) into the global matrix. 7879c789d87fSToby Isaac modMat is that matrix C */ 7880c789d87fSToby Isaac PetscCall(DMPlexAnchorsGetSubMatModification(dm, section, numPoints, numIndices, points, perms, outNumPoints, &newNumIndices, outPoints, offsets, outValues ? &modMat : NULL)); 7881c789d87fSToby Isaac if (outNumIndices) *outNumIndices = newNumIndices; 7882c789d87fSToby Isaac if (modMat) { 7883c789d87fSToby Isaac const PetscScalar *newValues = values; 78847cd05799SMatthew G. Knepley 7885c789d87fSToby Isaac if (multiplyRight) { 7886c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7887*6497c311SBarry Smith PetscBLASInt M, N, K; 7888c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 78897cd05799SMatthew G. Knepley 7890c789d87fSToby Isaac PetscCheck(numCols == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of columns: %" PetscInt_FMT ", expected %" PetscInt_FMT, numCols, numIndices); 78917cd05799SMatthew G. Knepley 7892*6497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &M)); 7893*6497c311SBarry Smith PetscCall(PetscBLASIntCast(numRows, &N)); 7894*6497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 7895c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, numRows * newNumIndices, MPIU_SCALAR, &newNewValues)); 7896c789d87fSToby Isaac // row-major to column-major conversion, right multiplication becomes left multiplication 7897c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &M, &N, &K, &a, modMat, &M, newValues, &K, &b, newNewValues, &M)); 7898c789d87fSToby Isaac numCols = newNumIndices; 7899c789d87fSToby Isaac newValues = newNewValues; 7900c789d87fSToby Isaac } 7901a1cb98faSBarry Smith 7902c789d87fSToby Isaac if (multiplyLeft) { 7903c789d87fSToby Isaac PetscScalar *newNewValues = NULL; 7904*6497c311SBarry Smith PetscBLASInt M, N, K; 7905c789d87fSToby Isaac PetscScalar a = 1.0, b = 0.0; 79067cd05799SMatthew G. Knepley 7907c789d87fSToby Isaac PetscCheck(numRows == numIndices, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "values matrix has the wrong number of rows: %" PetscInt_FMT ", expected %" PetscInt_FMT, numRows, numIndices); 7908c789d87fSToby Isaac 7909*6497c311SBarry Smith PetscCall(PetscBLASIntCast(numCols, &M)); 7910*6497c311SBarry Smith PetscCall(PetscBLASIntCast(newNumIndices, &N)); 7911*6497c311SBarry Smith PetscCall(PetscBLASIntCast(numIndices, &K)); 7912c789d87fSToby Isaac PetscCall(DMGetWorkArray(dm, newNumIndices * numCols, MPIU_SCALAR, &newNewValues)); 7913c789d87fSToby Isaac // row-major to column-major conversion, left multiplication becomes right multiplication 7914c789d87fSToby Isaac PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &M, &N, &K, &a, newValues, &M, modMat, &N, &b, newNewValues, &M)); 7915c789d87fSToby Isaac if (newValues != values) PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &newValues)); 7916c789d87fSToby Isaac newValues = newNewValues; 7917c789d87fSToby Isaac } 7918c789d87fSToby Isaac *outValues = (PetscScalar *)newValues; 7919c789d87fSToby Isaac PetscCall(DMRestoreWorkArray(dm, numIndices * newNumIndices, MPIU_SCALAR, &modMat)); 7920c789d87fSToby Isaac } 7921c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7922c789d87fSToby Isaac } 7923c789d87fSToby Isaac 7924c789d87fSToby Isaac PETSC_INTERN 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) 7925c789d87fSToby Isaac { 7926c789d87fSToby Isaac PetscFunctionBegin; 7927c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, numPoints, numIndices, points, perms, numIndices, numIndices, values, outNumPoints, outNumIndices, outPoints, outValues, offsets, PETSC_TRUE, multiplyLeft)); 7928c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7929c789d87fSToby Isaac } 7930c789d87fSToby Isaac 7931c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndicesSize_Internal(DM dm, PetscSection section, PetscInt point, PetscInt *closureSize) 7932c789d87fSToby Isaac { 7933c789d87fSToby Isaac /* Closure ordering */ 7934c789d87fSToby Isaac PetscSection clSection; 7935c789d87fSToby Isaac IS clPoints; 7936c789d87fSToby Isaac const PetscInt *clp; 7937c789d87fSToby Isaac PetscInt *points; 7938c789d87fSToby Isaac PetscInt Ncl, Ni = 0; 7939c789d87fSToby Isaac 7940c789d87fSToby Isaac PetscFunctionBeginHot; 7941c789d87fSToby Isaac PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7942c789d87fSToby Isaac for (PetscInt p = 0; p < Ncl * 2; p += 2) { 7943c789d87fSToby Isaac PetscInt dof; 7944c789d87fSToby Isaac 7945c789d87fSToby Isaac PetscCall(PetscSectionGetDof(section, points[p], &dof)); 7946c789d87fSToby Isaac Ni += dof; 7947c789d87fSToby Isaac } 7948c789d87fSToby Isaac PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 7949c789d87fSToby Isaac *closureSize = Ni; 7950c789d87fSToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 7951c789d87fSToby Isaac } 7952c789d87fSToby Isaac 7953c789d87fSToby Isaac static PetscErrorCode DMPlexGetClosureIndices_Internal(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numRows, PetscInt *numCols, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[], PetscBool multiplyRight, PetscBool multiplyLeft) 7954d71ae5a4SJacob Faibussowitsch { 795571f0bbf9SMatthew G. Knepley /* Closure ordering */ 79567773e69fSMatthew G. Knepley PetscSection clSection; 79577773e69fSMatthew G. Knepley IS clPoints; 795871f0bbf9SMatthew G. Knepley const PetscInt *clp; 795971f0bbf9SMatthew G. Knepley PetscInt *points; 796071f0bbf9SMatthew G. Knepley const PetscInt *clperm = NULL; 796171f0bbf9SMatthew G. Knepley /* Dof permutation and sign flips */ 79624acb8e1eSToby Isaac const PetscInt **perms[32] = {NULL}; 796371f0bbf9SMatthew G. Knepley const PetscScalar **flips[32] = {NULL}; 796471f0bbf9SMatthew G. Knepley PetscScalar *valCopy = NULL; 796571f0bbf9SMatthew G. Knepley /* Hanging node constraints */ 796671f0bbf9SMatthew G. Knepley PetscInt *pointsC = NULL; 796771f0bbf9SMatthew G. Knepley PetscScalar *valuesC = NULL; 796871f0bbf9SMatthew G. Knepley PetscInt NclC, NiC; 796971f0bbf9SMatthew G. Knepley 797071f0bbf9SMatthew G. Knepley PetscInt *idx; 797171f0bbf9SMatthew G. Knepley PetscInt Nf, Ncl, Ni = 0, offsets[32], p, f; 797271f0bbf9SMatthew G. Knepley PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE; 79737caea556SToby Isaac PetscInt idxStart, idxEnd; 7974c789d87fSToby Isaac PetscInt nRows, nCols; 79757773e69fSMatthew G. Knepley 797671f0bbf9SMatthew G. Knepley PetscFunctionBeginHot; 79777773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 79787773e69fSMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 797936fa2b79SJed Brown PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3); 7980c789d87fSToby Isaac PetscAssertPointer(numRows, 6); 7981c789d87fSToby Isaac PetscAssertPointer(numCols, 7); 7982c789d87fSToby Isaac if (indices) PetscAssertPointer(indices, 8); 7983c789d87fSToby Isaac if (outOffsets) PetscAssertPointer(outOffsets, 9); 7984c789d87fSToby Isaac if (values) PetscAssertPointer(values, 10); 79859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 798663a3b9bcSJacob Faibussowitsch PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf); 79879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(offsets, 32)); 798871f0bbf9SMatthew G. Knepley /* 1) Get points in closure */ 798907218a29SMatthew G. Knepley PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp)); 7990c459fbc1SJed Brown if (useClPerm) { 7991c459fbc1SJed Brown PetscInt depth, clsize; 79929566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &depth)); 7993c459fbc1SJed Brown for (clsize = 0, p = 0; p < Ncl; p++) { 7994c459fbc1SJed Brown PetscInt dof; 79959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[2 * p], &dof)); 7996c459fbc1SJed Brown clsize += dof; 7997c459fbc1SJed Brown } 79989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm)); 7999c459fbc1SJed Brown } 800071f0bbf9SMatthew G. Knepley /* 2) Get number of indices on these points and field offsets from section */ 800171f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl * 2; p += 2) { 80027773e69fSMatthew G. Knepley PetscInt dof, fdof; 80037773e69fSMatthew G. Knepley 80049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, points[p], &dof)); 80057773e69fSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 80069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof)); 80077773e69fSMatthew G. Knepley offsets[f + 1] += fdof; 80087773e69fSMatthew G. Knepley } 800971f0bbf9SMatthew G. Knepley Ni += dof; 80107773e69fSMatthew G. Knepley } 8011c789d87fSToby Isaac if (*numRows == -1) *numRows = Ni; 8012c789d87fSToby Isaac if (*numCols == -1) *numCols = Ni; 8013c789d87fSToby Isaac nRows = *numRows; 8014c789d87fSToby Isaac nCols = *numCols; 80157773e69fSMatthew G. Knepley for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f]; 80161dca8a05SBarry 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); 801771f0bbf9SMatthew G. Knepley /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */ 8018c789d87fSToby Isaac if (multiplyRight) PetscCheck(nCols == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " columns, got %" PetscInt_FMT, Ni, nCols); 8019c789d87fSToby Isaac if (multiplyLeft) PetscCheck(nRows == Ni, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Expected %" PetscInt_FMT " rows, got %" PetscInt_FMT, Ni, nRows); 802071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80219566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80229566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f])); 802371f0bbf9SMatthew G. Knepley /* may need to apply sign changes to the element matrix */ 802471f0bbf9SMatthew G. Knepley if (values && flips[f]) { 802571f0bbf9SMatthew G. Knepley PetscInt foffset = offsets[f]; 80266ecaa68aSToby Isaac 802771f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 802871f0bbf9SMatthew G. Knepley PetscInt pnt = points[2 * p], fdof; 802971f0bbf9SMatthew G. Knepley const PetscScalar *flip = flips[f] ? flips[f][p] : NULL; 803071f0bbf9SMatthew G. Knepley 80319566063dSJacob Faibussowitsch if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof)); 80329566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof)); 803371f0bbf9SMatthew G. Knepley if (flip) { 803471f0bbf9SMatthew G. Knepley PetscInt i, j, k; 803571f0bbf9SMatthew G. Knepley 803671f0bbf9SMatthew G. Knepley if (!valCopy) { 80379566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 803871f0bbf9SMatthew G. Knepley for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j]; 803971f0bbf9SMatthew G. Knepley *values = valCopy; 804071f0bbf9SMatthew G. Knepley } 804171f0bbf9SMatthew G. Knepley for (i = 0; i < fdof; ++i) { 804271f0bbf9SMatthew G. Knepley PetscScalar fval = flip[i]; 804371f0bbf9SMatthew G. Knepley 8044c789d87fSToby Isaac if (multiplyRight) { 8045c789d87fSToby Isaac for (k = 0; k < nRows; ++k) { valCopy[Ni * k + (foffset + i)] *= fval; } 8046c789d87fSToby Isaac } 8047c789d87fSToby Isaac if (multiplyLeft) { 8048c789d87fSToby Isaac for (k = 0; k < nCols; ++k) { valCopy[nCols * (foffset + i) + k] *= fval; } 80496ecaa68aSToby Isaac } 80506ecaa68aSToby Isaac } 805171f0bbf9SMatthew G. Knepley } 805271f0bbf9SMatthew G. Knepley foffset += fdof; 805371f0bbf9SMatthew G. Knepley } 805471f0bbf9SMatthew G. Knepley } 805571f0bbf9SMatthew G. Knepley } 805671f0bbf9SMatthew G. Knepley /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */ 8057c789d87fSToby Isaac PetscCall(DMPlexAnchorsModifyMat_Internal(dm, section, Ncl, Ni, points, perms, nRows, nCols, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, multiplyRight, multiplyLeft)); 805871f0bbf9SMatthew G. Knepley if (NclC) { 8059c789d87fSToby Isaac if (multiplyRight) { *numCols = nCols = NiC; } 8060c789d87fSToby Isaac if (multiplyLeft) { *numRows = nRows = NiC; } 80619566063dSJacob Faibussowitsch if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy)); 806271f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80639566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 80649566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 806571f0bbf9SMatthew G. Knepley } 806671f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 80679566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f])); 80689566063dSJacob Faibussowitsch else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f])); 806971f0bbf9SMatthew G. Knepley } 80709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 807171f0bbf9SMatthew G. Knepley Ncl = NclC; 807271f0bbf9SMatthew G. Knepley Ni = NiC; 807371f0bbf9SMatthew G. Knepley points = pointsC; 807471f0bbf9SMatthew G. Knepley if (values) *values = valuesC; 807571f0bbf9SMatthew G. Knepley } 807671f0bbf9SMatthew G. Knepley /* 5) Calculate indices */ 80779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx)); 80787caea556SToby Isaac PetscCall(PetscSectionGetChart(idxSection, &idxStart, &idxEnd)); 807971f0bbf9SMatthew G. Knepley if (Nf) { 808071f0bbf9SMatthew G. Knepley PetscInt idxOff; 808171f0bbf9SMatthew G. Knepley PetscBool useFieldOffsets; 808271f0bbf9SMatthew G. Knepley 80839371c9d4SSatish Balay if (outOffsets) { 80849371c9d4SSatish Balay for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f]; 80859371c9d4SSatish Balay } 80869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets)); 808771f0bbf9SMatthew G. Knepley if (useFieldOffsets) { 808871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 808971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 809071f0bbf9SMatthew G. Knepley 80919566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx)); 80927773e69fSMatthew G. Knepley } 80937773e69fSMatthew G. Knepley } else { 809471f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 809571f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 809671f0bbf9SMatthew G. Knepley 80977caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 80989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 809971f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 810071f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the 810171f0bbf9SMatthew G. Knepley * global section. */ 81029566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx)); 810371f0bbf9SMatthew G. Knepley } 810471f0bbf9SMatthew G. Knepley } 810571f0bbf9SMatthew G. Knepley } else { 810671f0bbf9SMatthew G. Knepley PetscInt off = 0, idxOff; 810771f0bbf9SMatthew G. Knepley 810871f0bbf9SMatthew G. Knepley for (p = 0; p < Ncl; ++p) { 810971f0bbf9SMatthew G. Knepley const PetscInt pnt = points[p * 2]; 81104acb8e1eSToby Isaac const PetscInt *perm = perms[0] ? perms[0][p] : NULL; 81114acb8e1eSToby Isaac 81127caea556SToby Isaac if (pnt < idxStart || pnt >= idxEnd) continue; 81139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff)); 811471f0bbf9SMatthew G. Knepley /* Note that we pass a local section even though we're using global offsets. This is because global sections do 811571f0bbf9SMatthew G. Knepley * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */ 81169566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx)); 81177773e69fSMatthew G. Knepley } 81187773e69fSMatthew G. Knepley } 811971f0bbf9SMatthew G. Knepley /* 6) Cleanup */ 812071f0bbf9SMatthew G. Knepley for (f = 0; f < PetscMax(1, Nf); ++f) { 81219566063dSJacob Faibussowitsch if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f])); 81229566063dSJacob Faibussowitsch else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f])); 81234acb8e1eSToby Isaac } 812471f0bbf9SMatthew G. Knepley if (NclC) { 81259566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC)); 81267773e69fSMatthew G. Knepley } else { 81279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp)); 81287773e69fSMatthew G. Knepley } 812971f0bbf9SMatthew G. Knepley 813071f0bbf9SMatthew G. Knepley if (indices) *indices = idx; 81313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 81327773e69fSMatthew G. Knepley } 81337773e69fSMatthew G. Knepley 8134d3d1a6afSToby Isaac /*@C 8135d3d1a6afSToby Isaac DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections. 8136d3d1a6afSToby Isaac 8137d3d1a6afSToby Isaac Not collective 8138d3d1a6afSToby Isaac 8139d3d1a6afSToby Isaac Input Parameters: 8140d3d1a6afSToby Isaac + dm - The `DM` 8141d3d1a6afSToby Isaac . section - The `PetscSection` describing the points (a local section) 8142d3d1a6afSToby Isaac . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 8143d3d1a6afSToby Isaac . point - The point defining the closure 8144d3d1a6afSToby Isaac - useClPerm - Use the closure point permutation if available 8145d3d1a6afSToby Isaac 8146d3d1a6afSToby Isaac Output Parameters: 8147d3d1a6afSToby Isaac + numIndices - The number of dof indices in the closure of point with the input sections 8148d3d1a6afSToby Isaac . indices - The dof indices 8149d3d1a6afSToby Isaac . outOffsets - Array to write the field offsets into, or `NULL` 8150d3d1a6afSToby Isaac - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 8151d3d1a6afSToby Isaac 8152d3d1a6afSToby Isaac Level: advanced 8153d3d1a6afSToby Isaac 8154d3d1a6afSToby Isaac Notes: 81552c9a7b26SBarry Smith Call `DMPlexRestoreClosureIndices()` to free allocated memory 8156d3d1a6afSToby Isaac 8157d3d1a6afSToby Isaac If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 8158d3d1a6afSToby Isaac of those indices is not significant. If `idxSection` is local, the constrained dofs will yield the involution -(idx+1) 8159d3d1a6afSToby Isaac of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 8160d3d1a6afSToby Isaac indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when `idxSection` == section, otherwise global 8161d3d1a6afSToby Isaac indices (with the above semantics) are implied. 8162d3d1a6afSToby Isaac 8163d3d1a6afSToby Isaac .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, 8164d3d1a6afSToby Isaac `PetscSection`, `DMGetGlobalSection()` 8165d3d1a6afSToby Isaac @*/ 8166d3d1a6afSToby Isaac PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8167d3d1a6afSToby Isaac { 8168c789d87fSToby Isaac PetscInt numRows = -1, numCols = -1; 8169d3d1a6afSToby Isaac 8170d3d1a6afSToby Isaac PetscFunctionBeginHot; 8171c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dm, section, idxSection, point, useClPerm, &numRows, &numCols, indices, outOffsets, values, PETSC_TRUE, PETSC_TRUE)); 8172c789d87fSToby Isaac PetscCheck(numRows == numCols, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Symmetric matrix transformation produces rectangular dimensions (%" PetscInt_FMT ", %" PetscInt_FMT ")", numRows, numCols); 8173c789d87fSToby Isaac *numIndices = numRows; 81747773e69fSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 81757773e69fSMatthew G. Knepley } 81767773e69fSMatthew G. Knepley 81777cd05799SMatthew G. Knepley /*@C 817871f0bbf9SMatthew G. Knepley DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections. 81797cd05799SMatthew G. Knepley 81807cd05799SMatthew G. Knepley Not collective 81817cd05799SMatthew G. Knepley 81827cd05799SMatthew G. Knepley Input Parameters: 8183a1cb98faSBarry Smith + dm - The `DM` 8184a1cb98faSBarry Smith . section - The `PetscSection` describing the points (a local section) 8185a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global) 818671f0bbf9SMatthew G. Knepley . point - The point defining the closure 818771f0bbf9SMatthew G. Knepley - useClPerm - Use the closure point permutation if available 818871f0bbf9SMatthew G. Knepley 818971f0bbf9SMatthew G. Knepley Output Parameters: 819071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections 819171f0bbf9SMatthew G. Knepley . indices - The dof indices 819220f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL` 819320f4b53cSBarry Smith - values - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL` 819471f0bbf9SMatthew G. Knepley 8195a1cb98faSBarry Smith Level: advanced 819671f0bbf9SMatthew G. Knepley 8197a1cb98faSBarry Smith Notes: 8198a1cb98faSBarry Smith If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values). 8199a1cb98faSBarry Smith 8200a1cb98faSBarry Smith If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices. The value 820171f0bbf9SMatthew G. Knepley of those indices is not significant. If idxSection is local, the constrained dofs will yield the involution -(idx+1) 820271f0bbf9SMatthew G. Knepley of their index in a local vector. A caller who does not wish to distinguish those points may recover the nonnegative 820371f0bbf9SMatthew G. Knepley indices via involution, -(-(idx+1)+1)==idx. Local indices are provided when idxSection == section, otherwise global 820471f0bbf9SMatthew G. Knepley indices (with the above semantics) are implied. 82057cd05799SMatthew G. Knepley 82061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()` 82077cd05799SMatthew G. Knepley @*/ 8208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) 8209d71ae5a4SJacob Faibussowitsch { 82107773e69fSMatthew G. Knepley PetscFunctionBegin; 82117773e69fSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82124f572ea9SToby Isaac PetscAssertPointer(indices, 7); 82139566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices)); 82143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82157773e69fSMatthew G. Knepley } 82167773e69fSMatthew G. Knepley 8217e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure_Internal(DM dm, PetscSection section, PetscSection globalSection, PetscBool useClPerm, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8218d71ae5a4SJacob Faibussowitsch { 8219552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8220552f7358SJed Brown PetscInt *indices; 822171f0bbf9SMatthew G. Knepley PetscInt numIndices; 822271f0bbf9SMatthew G. Knepley const PetscScalar *valuesOrig = values; 8223552f7358SJed Brown PetscErrorCode ierr; 8224552f7358SJed Brown 8225552f7358SJed Brown PetscFunctionBegin; 8226552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 82279566063dSJacob Faibussowitsch if (!section) PetscCall(DMGetLocalSection(dm, §ion)); 82283dc93601SMatthew G. Knepley PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 82299566063dSJacob Faibussowitsch if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection)); 82303dc93601SMatthew G. Knepley PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 8231e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 5); 8232552f7358SJed Brown 8233e8e188d2SZach Atkins PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, useClPerm, &numIndices, &indices, NULL, (PetscScalar **)&values)); 82340d644c17SKarl Rupp 82359566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values)); 8236d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 82374a1e0b3eSMatthew G. Knepley ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8238552f7358SJed Brown if (ierr) { 8239552f7358SJed Brown PetscMPIInt rank; 8240552f7358SJed Brown 82419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 82429566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 82439566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values)); 82449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 82459566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 8246c3e24edfSBarry Smith SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values"); 8247552f7358SJed Brown } 82484a1e0b3eSMatthew G. Knepley if (mesh->printFEM > 1) { 82494a1e0b3eSMatthew G. Knepley PetscInt i; 82509566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " Indices:")); 825163a3b9bcSJacob Faibussowitsch for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i])); 82529566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 82534a1e0b3eSMatthew G. Knepley } 825471f0bbf9SMatthew G. Knepley 82559566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values)); 82569566063dSJacob Faibussowitsch if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values)); 82573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 82584acb8e1eSToby Isaac } 825971f0bbf9SMatthew G. Knepley 82604a1e0b3eSMatthew G. Knepley /*@C 8261e8e188d2SZach Atkins DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 8262e8e188d2SZach Atkins 8263e8e188d2SZach Atkins Not collective 8264e8e188d2SZach Atkins 8265e8e188d2SZach Atkins Input Parameters: 8266e8e188d2SZach Atkins + dm - The `DM` 8267e8e188d2SZach Atkins . section - The section describing the layout in `v`, or `NULL` to use the default section 8268e8e188d2SZach Atkins . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section 8269e8e188d2SZach Atkins . A - The matrix 8270e8e188d2SZach Atkins . point - The point in the `DM` 8271e8e188d2SZach Atkins . values - The array of values 8272e8e188d2SZach Atkins - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 8273e8e188d2SZach Atkins 8274e8e188d2SZach Atkins Level: intermediate 8275e8e188d2SZach Atkins 8276e8e188d2SZach Atkins .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 8277e8e188d2SZach Atkins @*/ 8278e8e188d2SZach Atkins PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8279e8e188d2SZach Atkins { 8280e8e188d2SZach Atkins PetscFunctionBegin; 8281e8e188d2SZach Atkins PetscCall(DMPlexMatSetClosure_Internal(dm, section, globalSection, PETSC_TRUE, A, point, values, mode)); 8282e8e188d2SZach Atkins PetscFunctionReturn(PETSC_SUCCESS); 8283e8e188d2SZach Atkins } 8284e8e188d2SZach Atkins 8285e8e188d2SZach Atkins /*@C 828660225df5SJacob Faibussowitsch DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section 82874a1e0b3eSMatthew G. Knepley 82884a1e0b3eSMatthew G. Knepley Not collective 82894a1e0b3eSMatthew G. Knepley 82904a1e0b3eSMatthew G. Knepley Input Parameters: 8291a1cb98faSBarry Smith + dmRow - The `DM` for the row fields 829220f4b53cSBarry Smith . sectionRow - The section describing the layout, or `NULL` to use the default section in `dmRow` 8293e8e188d2SZach Atkins . useRowPerm - The flag to use the closure permutation of the `dmRow` if available 829420f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow` 8295a1cb98faSBarry Smith . dmCol - The `DM` for the column fields 829620f4b53cSBarry Smith . sectionCol - The section describing the layout, or `NULL` to use the default section in `dmCol` 8297e8e188d2SZach Atkins . useColPerm - The flag to use the closure permutation of the `dmCol` if available 829820f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol` 82994a1e0b3eSMatthew G. Knepley . A - The matrix 8300a1cb98faSBarry Smith . point - The point in the `DM` 83014a1e0b3eSMatthew G. Knepley . values - The array of values 8302a1cb98faSBarry Smith - mode - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions 83034a1e0b3eSMatthew G. Knepley 83044a1e0b3eSMatthew G. Knepley Level: intermediate 83054a1e0b3eSMatthew G. Knepley 83061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()` 83074a1e0b3eSMatthew G. Knepley @*/ 8308e8e188d2SZach 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) 8309d71ae5a4SJacob Faibussowitsch { 831071f0bbf9SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmRow->data; 831171f0bbf9SMatthew G. Knepley PetscInt *indicesRow, *indicesCol; 8312c789d87fSToby Isaac PetscInt numIndicesRow = -1, numIndicesCol = -1; 83137caea556SToby Isaac const PetscScalar *valuesV0 = values, *valuesV1, *valuesV2; 8314c789d87fSToby Isaac 831571f0bbf9SMatthew G. Knepley PetscErrorCode ierr; 831671f0bbf9SMatthew G. Knepley 831771f0bbf9SMatthew G. Knepley PetscFunctionBegin; 831871f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1); 83199566063dSJacob Faibussowitsch if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, §ionRow)); 832071f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2); 83219566063dSJacob Faibussowitsch if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow)); 832271f0bbf9SMatthew G. Knepley PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3); 8323e8e188d2SZach Atkins PetscValidHeaderSpecific(dmCol, DM_CLASSID, 5); 83249566063dSJacob Faibussowitsch if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, §ionCol)); 8325e8e188d2SZach Atkins PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 6); 83269566063dSJacob Faibussowitsch if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol)); 8327e8e188d2SZach Atkins PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 7); 8328e8e188d2SZach Atkins PetscValidHeaderSpecific(A, MAT_CLASSID, 9); 832971f0bbf9SMatthew G. Knepley 8330c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmRow, sectionRow, point, &numIndicesRow)); 8331c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndicesSize_Internal(dmCol, sectionCol, point, &numIndicesCol)); 83327caea556SToby Isaac valuesV1 = valuesV0; 8333c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV1, PETSC_FALSE, PETSC_TRUE)); 83347caea556SToby Isaac valuesV2 = valuesV1; 8335c789d87fSToby Isaac PetscCall(DMPlexGetClosureIndices_Internal(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesRow, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2, PETSC_TRUE, PETSC_FALSE)); 833671f0bbf9SMatthew G. Knepley 8337c789d87fSToby Isaac if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2)); 8338d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8339c789d87fSToby Isaac ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, valuesV2, mode); 834071f0bbf9SMatthew G. Knepley if (ierr) { 834171f0bbf9SMatthew G. Knepley PetscMPIInt rank; 834271f0bbf9SMatthew G. Knepley 83439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 83449566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 83459566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values)); 83467caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&valuesV2)); 83477caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 83487caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 83497caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 8350d3d1a6afSToby Isaac } 835171f0bbf9SMatthew G. Knepley 83527caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, useColPerm, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&valuesV2)); 83537caea556SToby Isaac PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, useRowPerm, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&valuesV1)); 83547caea556SToby Isaac if (valuesV2 != valuesV1) PetscCall(DMRestoreWorkArray(dmCol, 0, MPIU_SCALAR, &valuesV2)); 83557caea556SToby Isaac if (valuesV1 != valuesV0) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &valuesV1)); 83563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8357552f7358SJed Brown } 8358552f7358SJed Brown 8359d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 8360d71ae5a4SJacob Faibussowitsch { 8361de41b84cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dmf->data; 8362de41b84cSMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 8363de41b84cSMatthew G. Knepley PetscInt *cpoints = NULL; 8364de41b84cSMatthew G. Knepley PetscInt *findices, *cindices; 836517c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8366de41b84cSMatthew G. Knepley PetscInt foffsets[32], coffsets[32]; 8367412e9a14SMatthew G. Knepley DMPolytopeType ct; 83684ca5e9f5SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 8369de41b84cSMatthew G. Knepley PetscErrorCode ierr; 8370de41b84cSMatthew G. Knepley 8371de41b84cSMatthew G. Knepley PetscFunctionBegin; 8372de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 8373de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 83749566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 8375de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 83769566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 8377de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 83789566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 8379de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 83809566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 8381de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 8382de41b84cSMatthew G. Knepley PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 83839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 838463a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 83859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(foffsets, 32)); 83869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coffsets, 32)); 8387de41b84cSMatthew G. Knepley /* Column indices */ 83889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 83894ca5e9f5SMatthew G. Knepley maxFPoints = numCPoints; 8390de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 8391de41b84cSMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 83929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 8393de41b84cSMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 8394de41b84cSMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 8395de41b84cSMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 8396de41b84cSMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 8397de41b84cSMatthew G. Knepley ++q; 8398de41b84cSMatthew G. Knepley } 8399de41b84cSMatthew G. Knepley } 8400de41b84cSMatthew G. Knepley numCPoints = q; 8401de41b84cSMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 8402de41b84cSMatthew G. Knepley PetscInt fdof; 8403de41b84cSMatthew G. Knepley 84049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 84054ca5e9f5SMatthew G. Knepley if (!dof) continue; 8406de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 8408de41b84cSMatthew G. Knepley coffsets[f + 1] += fdof; 8409de41b84cSMatthew G. Knepley } 8410de41b84cSMatthew G. Knepley numCIndices += dof; 8411de41b84cSMatthew G. Knepley } 8412de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 8413de41b84cSMatthew G. Knepley /* Row indices */ 84149566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8415412e9a14SMatthew G. Knepley { 8416012bc364SMatthew G. Knepley DMPlexTransform tr; 8417012bc364SMatthew G. Knepley DMPolytopeType *rct; 8418012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8419012bc364SMatthew G. Knepley 84209566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 84219566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 84229566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8423012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 84249566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8425412e9a14SMatthew G. Knepley } 84269566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 8427de41b84cSMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 8428de41b84cSMatthew G. Knepley /* TODO Map from coarse to fine cells */ 84299566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 8430de41b84cSMatthew G. Knepley /* Compress out points not in the section */ 84319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 8432de41b84cSMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 8433de41b84cSMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 84349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 84354ca5e9f5SMatthew G. Knepley if (!dof) continue; 84369371c9d4SSatish Balay for (s = 0; s < q; ++s) 84379371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 84384ca5e9f5SMatthew G. Knepley if (s < q) continue; 8439de41b84cSMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 8440de41b84cSMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 8441de41b84cSMatthew G. Knepley ++q; 8442de41b84cSMatthew G. Knepley } 8443de41b84cSMatthew G. Knepley } 84449566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 8445de41b84cSMatthew G. Knepley } 8446de41b84cSMatthew G. Knepley numFPoints = q; 8447de41b84cSMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 8448de41b84cSMatthew G. Knepley PetscInt fdof; 8449de41b84cSMatthew G. Knepley 84509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 84514ca5e9f5SMatthew G. Knepley if (!dof) continue; 8452de41b84cSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 84539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 8454de41b84cSMatthew G. Knepley foffsets[f + 1] += fdof; 8455de41b84cSMatthew G. Knepley } 8456de41b84cSMatthew G. Knepley numFIndices += dof; 8457de41b84cSMatthew G. Knepley } 8458de41b84cSMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 8459de41b84cSMatthew G. Knepley 84601dca8a05SBarry 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); 84611dca8a05SBarry 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); 84629566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 84639566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8464de41b84cSMatthew G. Knepley if (numFields) { 84654acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 84664acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 84674acb8e1eSToby Isaac 84684acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8471de41b84cSMatthew G. Knepley } 84724acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 84739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84749566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 84754acb8e1eSToby Isaac } 84764acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 84779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 84789566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 84794acb8e1eSToby Isaac } 84804acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 84819566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 84829566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 8483de41b84cSMatthew G. Knepley } 8484de41b84cSMatthew G. Knepley } else { 84854acb8e1eSToby Isaac const PetscInt **permsF = NULL; 84864acb8e1eSToby Isaac const PetscInt **permsC = NULL; 84874acb8e1eSToby Isaac 84889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 84899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 84904acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 84914acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 84924acb8e1eSToby Isaac 84939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 84949566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 8495de41b84cSMatthew G. Knepley } 84964acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 84974acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 84984acb8e1eSToby Isaac 84999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 85009566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 8501de41b84cSMatthew G. Knepley } 85029566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 85039566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 8504de41b84cSMatthew G. Knepley } 85059566063dSJacob Faibussowitsch if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 85064acb8e1eSToby Isaac /* TODO: flips */ 8507d0609cedSBarry Smith /* TODO: fix this code to not use error codes as handle-able exceptions! */ 8508de41b84cSMatthew G. Knepley ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 8509de41b84cSMatthew G. Knepley if (ierr) { 8510de41b84cSMatthew G. Knepley PetscMPIInt rank; 8511de41b84cSMatthew G. Knepley 85129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 85139566063dSJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank)); 85149566063dSJacob Faibussowitsch PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values)); 85159566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 85169566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 8517de41b84cSMatthew G. Knepley } 85189566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 85199566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85209566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices)); 85219566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices)); 85223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8523de41b84cSMatthew G. Knepley } 8524de41b84cSMatthew G. Knepley 8525d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 8526d71ae5a4SJacob Faibussowitsch { 85277c927364SMatthew G. Knepley PetscInt *fpoints = NULL, *ftotpoints = NULL; 85287c927364SMatthew G. Knepley PetscInt *cpoints = NULL; 8529230af79eSStefano Zampini PetscInt foffsets[32] = {0}, coffsets[32] = {0}; 853017c0192bSMatthew G. Knepley const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */ 8531412e9a14SMatthew G. Knepley DMPolytopeType ct; 85327c927364SMatthew G. Knepley PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 85337c927364SMatthew G. Knepley 85347c927364SMatthew G. Knepley PetscFunctionBegin; 85357c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 85367c927364SMatthew G. Knepley PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 85379566063dSJacob Faibussowitsch if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection)); 85387c927364SMatthew G. Knepley PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 85399566063dSJacob Faibussowitsch if (!csection) PetscCall(DMGetLocalSection(dmc, &csection)); 85407c927364SMatthew G. Knepley PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 85419566063dSJacob Faibussowitsch if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 85427c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 85439566063dSJacob Faibussowitsch if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection)); 85447c927364SMatthew G. Knepley PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 85459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(fsection, &numFields)); 854663a3b9bcSJacob Faibussowitsch PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields); 85477c927364SMatthew G. Knepley /* Column indices */ 85489566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 85497c927364SMatthew G. Knepley maxFPoints = numCPoints; 85507c927364SMatthew G. Knepley /* Compress out points not in the section */ 85517c927364SMatthew G. Knepley /* TODO: Squeeze out points with 0 dof as well */ 85529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd)); 85537c927364SMatthew G. Knepley for (p = 0, q = 0; p < numCPoints * 2; p += 2) { 85547c927364SMatthew G. Knepley if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 85557c927364SMatthew G. Knepley cpoints[q * 2] = cpoints[p]; 85567c927364SMatthew G. Knepley cpoints[q * 2 + 1] = cpoints[p + 1]; 85577c927364SMatthew G. Knepley ++q; 85587c927364SMatthew G. Knepley } 85597c927364SMatthew G. Knepley } 85607c927364SMatthew G. Knepley numCPoints = q; 85617c927364SMatthew G. Knepley for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) { 85627c927364SMatthew G. Knepley PetscInt fdof; 85637c927364SMatthew G. Knepley 85649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof)); 85657c927364SMatthew G. Knepley if (!dof) continue; 85667c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 85679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof)); 85687c927364SMatthew G. Knepley coffsets[f + 1] += fdof; 85697c927364SMatthew G. Knepley } 85707c927364SMatthew G. Knepley numCIndices += dof; 85717c927364SMatthew G. Knepley } 85727c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f]; 85737c927364SMatthew G. Knepley /* Row indices */ 85749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dmc, point, &ct)); 8575412e9a14SMatthew G. Knepley { 8576012bc364SMatthew G. Knepley DMPlexTransform tr; 8577012bc364SMatthew G. Knepley DMPolytopeType *rct; 8578012bc364SMatthew G. Knepley PetscInt *rsize, *rcone, *rornt, Nt; 8579012bc364SMatthew G. Knepley 85809566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 85819566063dSJacob Faibussowitsch PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 85829566063dSJacob Faibussowitsch PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 8583012bc364SMatthew G. Knepley numSubcells = rsize[Nt - 1]; 85849566063dSJacob Faibussowitsch PetscCall(DMPlexTransformDestroy(&tr)); 8585412e9a14SMatthew G. Knepley } 85869566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints)); 85877c927364SMatthew G. Knepley for (r = 0, q = 0; r < numSubcells; ++r) { 85887c927364SMatthew G. Knepley /* TODO Map from coarse to fine cells */ 85899566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints)); 85907c927364SMatthew G. Knepley /* Compress out points not in the section */ 85919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd)); 85927c927364SMatthew G. Knepley for (p = 0; p < numFPoints * 2; p += 2) { 85937c927364SMatthew G. Knepley if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 85949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof)); 85957c927364SMatthew G. Knepley if (!dof) continue; 85969371c9d4SSatish Balay for (s = 0; s < q; ++s) 85979371c9d4SSatish Balay if (fpoints[p] == ftotpoints[s * 2]) break; 85987c927364SMatthew G. Knepley if (s < q) continue; 85997c927364SMatthew G. Knepley ftotpoints[q * 2] = fpoints[p]; 86007c927364SMatthew G. Knepley ftotpoints[q * 2 + 1] = fpoints[p + 1]; 86017c927364SMatthew G. Knepley ++q; 86027c927364SMatthew G. Knepley } 86037c927364SMatthew G. Knepley } 86049566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints)); 86057c927364SMatthew G. Knepley } 86067c927364SMatthew G. Knepley numFPoints = q; 86077c927364SMatthew G. Knepley for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) { 86087c927364SMatthew G. Knepley PetscInt fdof; 86097c927364SMatthew G. Knepley 86109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof)); 86117c927364SMatthew G. Knepley if (!dof) continue; 86127c927364SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 86139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof)); 86147c927364SMatthew G. Knepley foffsets[f + 1] += fdof; 86157c927364SMatthew G. Knepley } 86167c927364SMatthew G. Knepley numFIndices += dof; 86177c927364SMatthew G. Knepley } 86187c927364SMatthew G. Knepley for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f]; 86197c927364SMatthew G. Knepley 86201dca8a05SBarry 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); 86211dca8a05SBarry 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); 86227c927364SMatthew G. Knepley if (numFields) { 86234acb8e1eSToby Isaac const PetscInt **permsF[32] = {NULL}; 86244acb8e1eSToby Isaac const PetscInt **permsC[32] = {NULL}; 86254acb8e1eSToby Isaac 86264acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 86297c927364SMatthew G. Knepley } 86304acb8e1eSToby Isaac for (p = 0; p < numFPoints; p++) { 86319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86329566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices)); 86334acb8e1eSToby Isaac } 86344acb8e1eSToby Isaac for (p = 0; p < numCPoints; p++) { 86359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86369566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices)); 86374acb8e1eSToby Isaac } 86384acb8e1eSToby Isaac for (f = 0; f < numFields; f++) { 86399566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL)); 86409566063dSJacob Faibussowitsch PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL)); 86417c927364SMatthew G. Knepley } 86427c927364SMatthew G. Knepley } else { 86434acb8e1eSToby Isaac const PetscInt **permsF = NULL; 86444acb8e1eSToby Isaac const PetscInt **permsC = NULL; 86454acb8e1eSToby Isaac 86469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 86479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 86484acb8e1eSToby Isaac for (p = 0, off = 0; p < numFPoints; p++) { 86494acb8e1eSToby Isaac const PetscInt *perm = permsF ? permsF[p] : NULL; 86504acb8e1eSToby Isaac 86519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff)); 86529566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices)); 86537c927364SMatthew G. Knepley } 86544acb8e1eSToby Isaac for (p = 0, off = 0; p < numCPoints; p++) { 86554acb8e1eSToby Isaac const PetscInt *perm = permsC ? permsC[p] : NULL; 86564acb8e1eSToby Isaac 86579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff)); 86589566063dSJacob Faibussowitsch PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices)); 86597c927364SMatthew G. Knepley } 86609566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL)); 86619566063dSJacob Faibussowitsch PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL)); 86627c927364SMatthew G. Knepley } 86639566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints)); 86649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints)); 86653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 86667c927364SMatthew G. Knepley } 86677c927364SMatthew G. Knepley 8668cc4c1da9SBarry Smith /*@ 86697cd05799SMatthew G. Knepley DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0) 86707cd05799SMatthew G. Knepley 86717cd05799SMatthew G. Knepley Input Parameter: 8672a1cb98faSBarry Smith . dm - The `DMPLEX` object 86737cd05799SMatthew G. Knepley 86747cd05799SMatthew G. Knepley Output Parameter: 86757cd05799SMatthew G. Knepley . cellHeight - The height of a cell 86767cd05799SMatthew G. Knepley 86777cd05799SMatthew G. Knepley Level: developer 86787cd05799SMatthew G. Knepley 86791cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()` 86807cd05799SMatthew G. Knepley @*/ 8681d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8682d71ae5a4SJacob Faibussowitsch { 8683552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8684552f7358SJed Brown 8685552f7358SJed Brown PetscFunctionBegin; 8686552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 86874f572ea9SToby Isaac PetscAssertPointer(cellHeight, 2); 8688552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 86893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8690552f7358SJed Brown } 8691552f7358SJed Brown 8692cc4c1da9SBarry Smith /*@ 86937cd05799SMatthew G. Knepley DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0) 86947cd05799SMatthew G. Knepley 86957cd05799SMatthew G. Knepley Input Parameters: 8696a1cb98faSBarry Smith + dm - The `DMPLEX` object 86977cd05799SMatthew G. Knepley - cellHeight - The height of a cell 86987cd05799SMatthew G. Knepley 86997cd05799SMatthew G. Knepley Level: developer 87007cd05799SMatthew G. Knepley 87011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()` 87027cd05799SMatthew G. Knepley @*/ 8703d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8704d71ae5a4SJacob Faibussowitsch { 8705552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8706552f7358SJed Brown 8707552f7358SJed Brown PetscFunctionBegin; 8708552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8709552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 87103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8711552f7358SJed Brown } 8712552f7358SJed Brown 8713e6139122SMatthew G. Knepley /*@ 87142827ebadSStefano Zampini DMPlexGetCellTypeStratum - Get the range of cells of a given celltype 8715e6139122SMatthew G. Knepley 87162827ebadSStefano Zampini Input Parameters: 87172827ebadSStefano Zampini + dm - The `DMPLEX` object 87182827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell 8719e6139122SMatthew G. Knepley 8720e6139122SMatthew G. Knepley Output Parameters: 87212827ebadSStefano Zampini + start - The first cell of this type, or `NULL` 87222827ebadSStefano Zampini - end - The upper bound on this celltype, or `NULL` 8723e6139122SMatthew G. Knepley 87242a9f31c0SMatthew G. Knepley Level: advanced 8725e6139122SMatthew G. Knepley 87262827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()` 8727e6139122SMatthew G. Knepley @*/ 87282827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end) 8729d71ae5a4SJacob Faibussowitsch { 87302827ebadSStefano Zampini DM_Plex *mesh = (DM_Plex *)dm->data; 87312827ebadSStefano Zampini DMLabel label; 87322827ebadSStefano Zampini PetscInt pStart, pEnd; 8733e6139122SMatthew G. Knepley 8734e6139122SMatthew G. Knepley PetscFunctionBegin; 8735e6139122SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 87362827ebadSStefano Zampini if (start) { 87374f572ea9SToby Isaac PetscAssertPointer(start, 3); 87382827ebadSStefano Zampini *start = 0; 87392827ebadSStefano Zampini } 87402827ebadSStefano Zampini if (end) { 87414f572ea9SToby Isaac PetscAssertPointer(end, 4); 87422827ebadSStefano Zampini *end = 0; 87432827ebadSStefano Zampini } 87442827ebadSStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 87452827ebadSStefano Zampini if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS); 87462827ebadSStefano Zampini if (mesh->tr) { 87472827ebadSStefano Zampini PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end)); 87482827ebadSStefano Zampini } else { 87492827ebadSStefano Zampini PetscCall(DMPlexGetCellTypeLabel(dm, &label)); 87502827ebadSStefano Zampini PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found"); 87512827ebadSStefano Zampini PetscCall(DMLabelGetStratumBounds(label, ct, start, end)); 87522827ebadSStefano Zampini } 87533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8754e6139122SMatthew G. Knepley } 8755e6139122SMatthew G. Knepley 8756d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 8757d71ae5a4SJacob Faibussowitsch { 8758552f7358SJed Brown PetscSection section, globalSection; 8759552f7358SJed Brown PetscInt *numbers, p; 8760552f7358SJed Brown 8761552f7358SJed Brown PetscFunctionBegin; 8762d7d32a9aSMatthew G. Knepley if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE)); 87639566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 87649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 876548a46eb9SPierre Jolivet for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1)); 87669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 8767eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &globalSection)); 87689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &numbers)); 8769552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 87709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart])); 8771ef48cebcSMatthew G. Knepley if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift; 8772ef48cebcSMatthew G. Knepley else numbers[p - pStart] += shift; 8773552f7358SJed Brown } 87749566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering)); 8775ef48cebcSMatthew G. Knepley if (globalSize) { 8776ef48cebcSMatthew G. Knepley PetscLayout layout; 87779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout)); 87789566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetSize(layout, globalSize)); 87799566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 8780ef48cebcSMatthew G. Knepley } 87819566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 87829566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&globalSection)); 87833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8784552f7358SJed Brown } 8785552f7358SJed Brown 8786e2b8d0fcSMatthew G. Knepley /*@ 8787e2b8d0fcSMatthew G. Knepley DMPlexCreateCellNumbering - Get a global cell numbering for all cells on this process 8788e2b8d0fcSMatthew G. Knepley 8789bc9da2b0SJose E. Roman Input Parameters: 8790e2b8d0fcSMatthew G. Knepley + dm - The `DMPLEX` object 8791e2b8d0fcSMatthew G. Knepley - includeAll - Whether to include all cells, or just the simplex and box cells 8792e2b8d0fcSMatthew G. Knepley 8793e2b8d0fcSMatthew G. Knepley Output Parameter: 8794e2b8d0fcSMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 8795e2b8d0fcSMatthew G. Knepley 8796e2b8d0fcSMatthew G. Knepley Level: developer 8797e2b8d0fcSMatthew G. Knepley 8798e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()` 8799e2b8d0fcSMatthew G. Knepley @*/ 8800e2b8d0fcSMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering(DM dm, PetscBool includeAll, IS *globalCellNumbers) 8801d71ae5a4SJacob Faibussowitsch { 8802412e9a14SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd; 8803552f7358SJed Brown 8804552f7358SJed Brown PetscFunctionBegin; 88059566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 8806e2b8d0fcSMatthew G. Knepley if (includeAll) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 88079566063dSJacob Faibussowitsch else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd)); 88089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers)); 88093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8810552f7358SJed Brown } 881181ed3555SMatthew G. Knepley 88128dab3259SMatthew G. Knepley /*@ 88137cd05799SMatthew G. Knepley DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process 88147cd05799SMatthew G. Knepley 88157cd05799SMatthew G. Knepley Input Parameter: 8816a1cb98faSBarry Smith . dm - The `DMPLEX` object 88177cd05799SMatthew G. Knepley 88187cd05799SMatthew G. Knepley Output Parameter: 88197cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process 88207cd05799SMatthew G. Knepley 88217cd05799SMatthew G. Knepley Level: developer 88227cd05799SMatthew G. Knepley 8823e2b8d0fcSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateCellNumbering()`, `DMPlexGetVertexNumbering()` 88247cd05799SMatthew G. Knepley @*/ 8825d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 8826d71ae5a4SJacob Faibussowitsch { 882781ed3555SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 882881ed3555SMatthew G. Knepley 882981ed3555SMatthew G. Knepley PetscFunctionBegin; 883081ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8831e2b8d0fcSMatthew G. Knepley if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering(dm, PETSC_FALSE, &mesh->globalCellNumbers)); 8832552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 88333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8834552f7358SJed Brown } 8835552f7358SJed Brown 8836d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) 8837d71ae5a4SJacob Faibussowitsch { 8838412e9a14SMatthew G. Knepley PetscInt vStart, vEnd; 883981ed3555SMatthew G. Knepley 884081ed3555SMatthew G. Knepley PetscFunctionBegin; 884181ed3555SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88429566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 88439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers)); 88443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 884581ed3555SMatthew G. Knepley } 884681ed3555SMatthew G. Knepley 88478dab3259SMatthew G. Knepley /*@ 88486aa51ba9SJacob Faibussowitsch DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process 88497cd05799SMatthew G. Knepley 88507cd05799SMatthew G. Knepley Input Parameter: 8851a1cb98faSBarry Smith . dm - The `DMPLEX` object 88527cd05799SMatthew G. Knepley 88537cd05799SMatthew G. Knepley Output Parameter: 88547cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process 88557cd05799SMatthew G. Knepley 88567cd05799SMatthew G. Knepley Level: developer 88577cd05799SMatthew G. Knepley 88581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 88597cd05799SMatthew G. Knepley @*/ 8860d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 8861d71ae5a4SJacob Faibussowitsch { 8862552f7358SJed Brown DM_Plex *mesh = (DM_Plex *)dm->data; 8863552f7358SJed Brown 8864552f7358SJed Brown PetscFunctionBegin; 8865552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 88669566063dSJacob Faibussowitsch if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers)); 8867552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 88683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8869552f7358SJed Brown } 8870552f7358SJed Brown 88718dab3259SMatthew G. Knepley /*@ 8872966484cfSJed Brown DMPlexCreatePointNumbering - Create a global numbering for all points. 8873966484cfSJed Brown 887420f4b53cSBarry Smith Collective 88757cd05799SMatthew G. Knepley 88767cd05799SMatthew G. Knepley Input Parameter: 8877a1cb98faSBarry Smith . dm - The `DMPLEX` object 88787cd05799SMatthew G. Knepley 88797cd05799SMatthew G. Knepley Output Parameter: 88807cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process 88817cd05799SMatthew G. Knepley 8882a1cb98faSBarry Smith Level: developer 8883966484cfSJed Brown 8884a1cb98faSBarry Smith Notes: 8885a1cb98faSBarry Smith The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global 8886966484cfSJed Brown points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points 8887966484cfSJed Brown will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example, 8888966484cfSJed Brown consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0. 8889966484cfSJed Brown 8890966484cfSJed Brown The partitioned mesh is 8891966484cfSJed Brown ``` 8892966484cfSJed Brown (2)--0--(3)--1--(4) (1)--0--(2) 8893966484cfSJed Brown ``` 8894966484cfSJed Brown and its global numbering is 8895966484cfSJed Brown ``` 8896966484cfSJed Brown (3)--0--(4)--1--(5)--2--(6) 8897966484cfSJed Brown ``` 8898966484cfSJed Brown Then the global numbering is provided as 8899966484cfSJed Brown ``` 8900966484cfSJed Brown [0] Number of indices in set 5 8901966484cfSJed Brown [0] 0 0 8902966484cfSJed Brown [0] 1 1 8903966484cfSJed Brown [0] 2 3 8904966484cfSJed Brown [0] 3 4 8905966484cfSJed Brown [0] 4 -6 8906966484cfSJed Brown [1] Number of indices in set 3 8907966484cfSJed Brown [1] 0 2 8908966484cfSJed Brown [1] 1 5 8909966484cfSJed Brown [1] 2 6 8910966484cfSJed Brown ``` 8911966484cfSJed Brown 89121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()` 89137cd05799SMatthew G. Knepley @*/ 8914d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 8915d71ae5a4SJacob Faibussowitsch { 8916ef48cebcSMatthew G. Knepley IS nums[4]; 8917862913ffSStefano Zampini PetscInt depths[4], gdepths[4], starts[4]; 8918ef48cebcSMatthew G. Knepley PetscInt depth, d, shift = 0; 89190c15888dSMatthew G. Knepley PetscBool empty = PETSC_FALSE; 8920ef48cebcSMatthew G. Knepley 8921ef48cebcSMatthew G. Knepley PetscFunctionBegin; 8922ef48cebcSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 89239566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 89240c15888dSMatthew G. Knepley // For unstratified meshes use dim instead of depth 89259566063dSJacob Faibussowitsch if (depth < 0) PetscCall(DMGetDimension(dm, &depth)); 89260c15888dSMatthew G. Knepley // If any stratum is empty, we must mark all empty 8927862913ffSStefano Zampini for (d = 0; d <= depth; ++d) { 8928862913ffSStefano Zampini PetscInt end; 8929862913ffSStefano Zampini 8930862913ffSStefano Zampini depths[d] = depth - d; 89319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end)); 89320c15888dSMatthew G. Knepley if (!(starts[d] - end)) empty = PETSC_TRUE; 8933862913ffSStefano Zampini } 89340c15888dSMatthew G. Knepley if (empty) 89350c15888dSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 89360c15888dSMatthew G. Knepley depths[d] = -1; 89370c15888dSMatthew G. Knepley starts[d] = -1; 89380c15888dSMatthew G. Knepley } 89390c15888dSMatthew G. Knepley else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths)); 8940*6497c311SBarry Smith PetscCall(MPIU_Allreduce(depths, gdepths, (PetscMPIInt)(depth + 1), MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 8941ad540459SPierre 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]); 89420c15888dSMatthew G. Knepley // Note here that 'shift' is collective, so that the numbering is stratified by depth 8943ef48cebcSMatthew G. Knepley for (d = 0; d <= depth; ++d) { 8944ef48cebcSMatthew G. Knepley PetscInt pStart, pEnd, gsize; 8945ef48cebcSMatthew G. Knepley 89469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd)); 89479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d])); 8948ef48cebcSMatthew G. Knepley shift += gsize; 8949ef48cebcSMatthew G. Knepley } 8950d1c35871SJed Brown PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers)); 89519566063dSJacob Faibussowitsch for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d])); 89523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8953ef48cebcSMatthew G. Knepley } 8954ef48cebcSMatthew G. Knepley 895508a22f4bSMatthew G. Knepley /*@ 8956484edb7dSMatthew G. Knepley DMPlexCreateEdgeNumbering - Create a global numbering for edges. 8957484edb7dSMatthew G. Knepley 8958484edb7dSMatthew G. Knepley Collective 8959484edb7dSMatthew G. Knepley 8960484edb7dSMatthew G. Knepley Input Parameter: 8961484edb7dSMatthew G. Knepley . dm - The `DMPLEX` object 8962484edb7dSMatthew G. Knepley 8963484edb7dSMatthew G. Knepley Output Parameter: 8964484edb7dSMatthew G. Knepley . globalEdgeNumbers - Global numbers for all edges on this process 8965484edb7dSMatthew G. Knepley 8966484edb7dSMatthew G. Knepley Level: developer 8967484edb7dSMatthew G. Knepley 8968484edb7dSMatthew G. Knepley Notes: 8969484edb7dSMatthew G. Knepley The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). In the IS, owned edges will have their non-negative value while edges owned by different ranks will be involuted -(idx+1). 8970484edb7dSMatthew G. Knepley 8971484edb7dSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`, `DMPlexGetVertexNumbering()`, `DMPlexCreatePointNumbering()` 8972484edb7dSMatthew G. Knepley @*/ 8973484edb7dSMatthew G. Knepley PetscErrorCode DMPlexCreateEdgeNumbering(DM dm, IS *globalEdgeNumbers) 8974484edb7dSMatthew G. Knepley { 8975484edb7dSMatthew G. Knepley PetscSF sf; 8976484edb7dSMatthew G. Knepley PetscInt eStart, eEnd; 8977484edb7dSMatthew G. Knepley 8978484edb7dSMatthew G. Knepley PetscFunctionBegin; 8979484edb7dSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8980484edb7dSMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 8981484edb7dSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 8982484edb7dSMatthew G. Knepley PetscCall(DMPlexCreateNumbering_Plex(dm, eStart, eEnd, 0, NULL, sf, globalEdgeNumbers)); 8983484edb7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 8984484edb7dSMatthew G. Knepley } 8985484edb7dSMatthew G. Knepley 8986484edb7dSMatthew G. Knepley /*@ 898708a22f4bSMatthew G. Knepley DMPlexCreateRankField - Create a cell field whose value is the rank of the owner 898808a22f4bSMatthew G. Knepley 898908a22f4bSMatthew G. Knepley Input Parameter: 8990a1cb98faSBarry Smith . dm - The `DMPLEX` object 899108a22f4bSMatthew G. Knepley 899208a22f4bSMatthew G. Knepley Output Parameter: 899308a22f4bSMatthew G. Knepley . ranks - The rank field 899408a22f4bSMatthew G. Knepley 8995a1cb98faSBarry Smith Options Database Key: 899620f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer 899708a22f4bSMatthew G. Knepley 899808a22f4bSMatthew G. Knepley Level: intermediate 899908a22f4bSMatthew G. Knepley 90001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 900108a22f4bSMatthew G. Knepley @*/ 9002d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) 9003d71ae5a4SJacob Faibussowitsch { 900408a22f4bSMatthew G. Knepley DM rdm; 900508a22f4bSMatthew G. Knepley PetscFE fe; 900608a22f4bSMatthew G. Knepley PetscScalar *r; 900708a22f4bSMatthew G. Knepley PetscMPIInt rank; 9008a55f9a55SMatthew G. Knepley DMPolytopeType ct; 900908a22f4bSMatthew G. Knepley PetscInt dim, cStart, cEnd, c; 9010a55f9a55SMatthew G. Knepley PetscBool simplex; 901108a22f4bSMatthew G. Knepley 901208a22f4bSMatthew G. Knepley PetscFunctionBeginUser; 9013f95ace6aSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90144f572ea9SToby Isaac PetscAssertPointer(ranks, 2); 90159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 90169566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 90179566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 90189566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd)); 90199566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 9020a55f9a55SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 90219566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe)); 90229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "rank")); 90239566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 90249566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 90259566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 90269566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, ranks)); 90279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition")); 90289566063dSJacob Faibussowitsch PetscCall(VecGetArray(*ranks, &r)); 902908a22f4bSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 903008a22f4bSMatthew G. Knepley PetscScalar *lr; 903108a22f4bSMatthew G. Knepley 90329566063dSJacob Faibussowitsch PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr)); 903371f09efeSPierre Jolivet if (lr) *lr = rank; 903408a22f4bSMatthew G. Knepley } 90359566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(*ranks, &r)); 90369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 90373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 903808a22f4bSMatthew G. Knepley } 903908a22f4bSMatthew G. Knepley 9040ca8062c8SMatthew G. Knepley /*@ 9041acf3173eSStefano Zampini DMPlexCreateLabelField - Create a field whose value is the label value for that point 904218e14f0cSMatthew G. Knepley 904318e14f0cSMatthew G. Knepley Input Parameters: 904420f4b53cSBarry Smith + dm - The `DMPLEX` 904520f4b53cSBarry Smith - label - The `DMLabel` 904618e14f0cSMatthew G. Knepley 904718e14f0cSMatthew G. Knepley Output Parameter: 904818e14f0cSMatthew G. Knepley . val - The label value field 904918e14f0cSMatthew G. Knepley 905020f4b53cSBarry Smith Options Database Key: 905120f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer 905218e14f0cSMatthew G. Knepley 905318e14f0cSMatthew G. Knepley Level: intermediate 905418e14f0cSMatthew G. Knepley 90551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()` 905618e14f0cSMatthew G. Knepley @*/ 9057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) 9058d71ae5a4SJacob Faibussowitsch { 90591033741fSStefano Zampini DM rdm, plex; 9060acf3173eSStefano Zampini Vec lval; 9061acf3173eSStefano Zampini PetscSection section; 906218e14f0cSMatthew G. Knepley PetscFE fe; 906318e14f0cSMatthew G. Knepley PetscScalar *v; 9064acf3173eSStefano Zampini PetscInt dim, pStart, pEnd, p, cStart; 9065acf3173eSStefano Zampini DMPolytopeType ct; 9066acf3173eSStefano Zampini char name[PETSC_MAX_PATH_LEN]; 9067acf3173eSStefano Zampini const char *lname, *prefix; 906818e14f0cSMatthew G. Knepley 906918e14f0cSMatthew G. Knepley PetscFunctionBeginUser; 907018e14f0cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 90714f572ea9SToby Isaac PetscAssertPointer(label, 2); 90724f572ea9SToby Isaac PetscAssertPointer(val, 3); 90739566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &rdm)); 9074acf3173eSStefano Zampini PetscCall(DMConvert(rdm, DMPLEX, &plex)); 9075acf3173eSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, NULL)); 9076acf3173eSStefano Zampini PetscCall(DMPlexGetCellType(plex, cStart, &ct)); 9077acf3173eSStefano Zampini PetscCall(DMDestroy(&plex)); 90789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(rdm, &dim)); 9079acf3173eSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 9080acf3173eSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 9081acf3173eSStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "%s%s_", prefix ? prefix : "", lname)); 9082acf3173eSStefano Zampini PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, name, -1, &fe)); 9083acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)fe, "")); 90849566063dSJacob Faibussowitsch PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe)); 90859566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 90869566063dSJacob Faibussowitsch PetscCall(DMCreateDS(rdm)); 90879566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(rdm, val)); 9088acf3173eSStefano Zampini PetscCall(DMCreateLocalVector(rdm, &lval)); 9089acf3173eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*val, lname)); 9090acf3173eSStefano Zampini PetscCall(DMGetLocalSection(rdm, §ion)); 9091acf3173eSStefano Zampini PetscCall(PetscSectionGetChart(section, &pStart, &pEnd)); 9092acf3173eSStefano Zampini PetscCall(VecGetArray(lval, &v)); 9093acf3173eSStefano Zampini for (p = pStart; p < pEnd; ++p) { 9094acf3173eSStefano Zampini PetscInt cval, dof, off; 909518e14f0cSMatthew G. Knepley 9096acf3173eSStefano Zampini PetscCall(PetscSectionGetDof(section, p, &dof)); 9097acf3173eSStefano Zampini if (!dof) continue; 9098acf3173eSStefano Zampini PetscCall(DMLabelGetValue(label, p, &cval)); 9099acf3173eSStefano Zampini PetscCall(PetscSectionGetOffset(section, p, &off)); 9100acf3173eSStefano Zampini for (PetscInt d = 0; d < dof; d++) v[off + d] = cval; 910118e14f0cSMatthew G. Knepley } 9102acf3173eSStefano Zampini PetscCall(VecRestoreArray(lval, &v)); 9103acf3173eSStefano Zampini PetscCall(DMLocalToGlobal(rdm, lval, INSERT_VALUES, *val)); 9104acf3173eSStefano Zampini PetscCall(VecDestroy(&lval)); 91059566063dSJacob Faibussowitsch PetscCall(DMDestroy(&rdm)); 91063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 910718e14f0cSMatthew G. Knepley } 910818e14f0cSMatthew G. Knepley 910918e14f0cSMatthew G. Knepley /*@ 9110ca8062c8SMatthew G. Knepley DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 9111ca8062c8SMatthew G. Knepley 911269916449SMatthew G. Knepley Input Parameter: 9113a1cb98faSBarry Smith . dm - The `DMPLEX` object 9114a1cb98faSBarry Smith 9115a1cb98faSBarry Smith Level: developer 9116ca8062c8SMatthew G. Knepley 911795eb5ee5SVaclav Hapla Notes: 911895eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 911995eb5ee5SVaclav Hapla 912020f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9121ca8062c8SMatthew G. Knepley 91221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9123ca8062c8SMatthew G. Knepley @*/ 9124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm) 9125d71ae5a4SJacob Faibussowitsch { 9126ca8062c8SMatthew G. Knepley PetscSection coneSection, supportSection; 9127ca8062c8SMatthew G. Knepley const PetscInt *cone, *support; 9128ca8062c8SMatthew G. Knepley PetscInt coneSize, c, supportSize, s; 912957beb4faSStefano Zampini PetscInt pStart, pEnd, p, pp, csize, ssize; 913057beb4faSStefano Zampini PetscBool storagecheck = PETSC_TRUE; 9131ca8062c8SMatthew G. Knepley 9132ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9133ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 91349566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view")); 91359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSection(dm, &coneSection)); 91369566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSection(dm, &supportSection)); 9137ca8062c8SMatthew G. Knepley /* Check that point p is found in the support of its cone points, and vice versa */ 91389566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9139ca8062c8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 91409566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &coneSize)); 91419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &cone)); 9142ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 914342e66dfaSMatthew G. Knepley PetscBool dup = PETSC_FALSE; 914442e66dfaSMatthew G. Knepley PetscInt d; 914542e66dfaSMatthew G. Knepley for (d = c - 1; d >= 0; --d) { 91469371c9d4SSatish Balay if (cone[c] == cone[d]) { 91479371c9d4SSatish Balay dup = PETSC_TRUE; 91489371c9d4SSatish Balay break; 91499371c9d4SSatish Balay } 915042e66dfaSMatthew G. Knepley } 91519566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize)); 91529566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[c], &support)); 9153ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 9154ca8062c8SMatthew G. Knepley if (support[s] == p) break; 9155ca8062c8SMatthew G. Knepley } 915642e66dfaSMatthew G. Knepley if ((s >= supportSize) || (dup && (support[s + 1] != p))) { 915763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p)); 915848a46eb9SPierre Jolivet for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s])); 91599566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 916063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c])); 916148a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s])); 91629566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 916363a3b9bcSJacob 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]); 9164f7d195e4SLawrence Mitchell SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]); 9165ca8062c8SMatthew G. Knepley } 916642e66dfaSMatthew G. Knepley } 91679566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 91689371c9d4SSatish Balay if (p != pp) { 91699371c9d4SSatish Balay storagecheck = PETSC_FALSE; 91709371c9d4SSatish Balay continue; 91719371c9d4SSatish Balay } 91729566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &supportSize)); 91739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &support)); 9174ca8062c8SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 91759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 91769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 9177ca8062c8SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 91789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL)); 91799371c9d4SSatish Balay if (cone[c] != pp) { 91809371c9d4SSatish Balay c = 0; 91819371c9d4SSatish Balay break; 91829371c9d4SSatish Balay } 9183ca8062c8SMatthew G. Knepley if (cone[c] == p) break; 9184ca8062c8SMatthew G. Knepley } 9185ca8062c8SMatthew G. Knepley if (c >= coneSize) { 918663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p)); 918748a46eb9SPierre Jolivet for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c])); 91889566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 918963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s])); 919048a46eb9SPierre Jolivet for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c])); 91919566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 919263a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]); 9193ca8062c8SMatthew G. Knepley } 9194ca8062c8SMatthew G. Knepley } 9195ca8062c8SMatthew G. Knepley } 919657beb4faSStefano Zampini if (storagecheck) { 91979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coneSection, &csize)); 91989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(supportSection, &ssize)); 919963a3b9bcSJacob Faibussowitsch PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize); 920057beb4faSStefano Zampini } 92013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9202ca8062c8SMatthew G. Knepley } 9203ca8062c8SMatthew G. Knepley 9204412e9a14SMatthew G. Knepley /* 9205412e9a14SMatthew 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. 9206412e9a14SMatthew G. Knepley */ 9207d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) 9208d71ae5a4SJacob Faibussowitsch { 9209412e9a14SMatthew G. Knepley DMPolytopeType cct; 9210412e9a14SMatthew G. Knepley PetscInt ptpoints[4]; 9211412e9a14SMatthew G. Knepley const PetscInt *cone, *ccone, *ptcone; 9212412e9a14SMatthew G. Knepley PetscInt coneSize, cp, cconeSize, ccp, npt = 0, pt; 9213412e9a14SMatthew G. Knepley 9214412e9a14SMatthew G. Knepley PetscFunctionBegin; 9215412e9a14SMatthew G. Knepley *unsplit = 0; 9216412e9a14SMatthew G. Knepley switch (ct) { 9217d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_POINT_PRISM_TENSOR: 9218d71ae5a4SJacob Faibussowitsch ptpoints[npt++] = c; 9219d71ae5a4SJacob Faibussowitsch break; 9220412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 92219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 92229566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9223412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 92249566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[cp], &cct)); 9225412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp]; 9226412e9a14SMatthew G. Knepley } 9227412e9a14SMatthew G. Knepley break; 9228412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9229412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 92309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 92319566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 9232412e9a14SMatthew G. Knepley for (cp = 0; cp < coneSize; ++cp) { 92339566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[cp], &ccone)); 92349566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize)); 9235412e9a14SMatthew G. Knepley for (ccp = 0; ccp < cconeSize; ++ccp) { 92369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct)); 9237412e9a14SMatthew G. Knepley if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 9238412e9a14SMatthew G. Knepley PetscInt p; 92399371c9d4SSatish Balay for (p = 0; p < npt; ++p) 92409371c9d4SSatish Balay if (ptpoints[p] == ccone[ccp]) break; 9241412e9a14SMatthew G. Knepley if (p == npt) ptpoints[npt++] = ccone[ccp]; 9242412e9a14SMatthew G. Knepley } 9243412e9a14SMatthew G. Knepley } 9244412e9a14SMatthew G. Knepley } 9245412e9a14SMatthew G. Knepley break; 9246d71ae5a4SJacob Faibussowitsch default: 9247d71ae5a4SJacob Faibussowitsch break; 9248412e9a14SMatthew G. Knepley } 9249412e9a14SMatthew G. Knepley for (pt = 0; pt < npt; ++pt) { 92509566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone)); 9251412e9a14SMatthew G. Knepley if (ptcone[0] == ptcone[1]) ++(*unsplit); 9252412e9a14SMatthew G. Knepley } 92533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9254412e9a14SMatthew G. Knepley } 9255412e9a14SMatthew G. Knepley 9256ca8062c8SMatthew G. Knepley /*@ 9257ca8062c8SMatthew G. Knepley DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 9258ca8062c8SMatthew G. Knepley 9259ca8062c8SMatthew G. Knepley Input Parameters: 9260a1cb98faSBarry Smith + dm - The `DMPLEX` object 926158723a97SMatthew G. Knepley - cellHeight - Normally 0 9262ca8062c8SMatthew G. Knepley 9263a1cb98faSBarry Smith Level: developer 9264a1cb98faSBarry Smith 926595eb5ee5SVaclav Hapla Notes: 926695eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 926725c50c26SVaclav Hapla Currently applicable only to homogeneous simplex or tensor meshes. 9268ca8062c8SMatthew G. Knepley 926920f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 927095eb5ee5SVaclav Hapla 92711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9272ca8062c8SMatthew G. Knepley @*/ 9273d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) 9274d71ae5a4SJacob Faibussowitsch { 9275412e9a14SMatthew G. Knepley DMPlexInterpolatedFlag interp; 9276412e9a14SMatthew G. Knepley DMPolytopeType ct; 9277412e9a14SMatthew G. Knepley PetscInt vStart, vEnd, cStart, cEnd, c; 9278ca8062c8SMatthew G. Knepley 9279ca8062c8SMatthew G. Knepley PetscFunctionBegin; 9280ca8062c8SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 92819566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interp)); 92829566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 92839566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9284412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9285412e9a14SMatthew G. Knepley PetscInt *closure = NULL; 9286412e9a14SMatthew G. Knepley PetscInt coneSize, closureSize, cl, Nv = 0; 928758723a97SMatthew G. Knepley 92889566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9289412e9a14SMatthew G. Knepley if (ct == DM_POLYTOPE_UNKNOWN) continue; 9290412e9a14SMatthew G. Knepley if (interp == DMPLEX_INTERPOLATED_FULL) { 92919566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 929263a3b9bcSJacob 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)); 9293412e9a14SMatthew G. Knepley } 92949566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 929558723a97SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 929658723a97SMatthew G. Knepley const PetscInt p = closure[cl]; 9297412e9a14SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) ++Nv; 929858723a97SMatthew G. Knepley } 92999566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 9300412e9a14SMatthew G. Knepley /* Special Case: Tensor faces with identified vertices */ 9301412e9a14SMatthew G. Knepley if (Nv < DMPolytopeTypeGetNumVertices(ct)) { 9302412e9a14SMatthew G. Knepley PetscInt unsplit; 930342363296SMatthew G. Knepley 93049566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9305412e9a14SMatthew G. Knepley if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue; 930642363296SMatthew G. Knepley } 930763a3b9bcSJacob 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)); 930842363296SMatthew G. Knepley } 93093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9310ca8062c8SMatthew G. Knepley } 93119bf0dad6SMatthew G. Knepley 93129bf0dad6SMatthew G. Knepley /*@ 93139bf0dad6SMatthew 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 93149bf0dad6SMatthew G. Knepley 931520f4b53cSBarry Smith Collective 9316899ea2b8SJacob Faibussowitsch 93179bf0dad6SMatthew G. Knepley Input Parameters: 9318a1cb98faSBarry Smith + dm - The `DMPLEX` object 93199bf0dad6SMatthew G. Knepley - cellHeight - Normally 0 93209bf0dad6SMatthew G. Knepley 9321a1cb98faSBarry Smith Level: developer 9322a1cb98faSBarry Smith 932345da879fSVaclav Hapla Notes: 932445da879fSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 932545da879fSVaclav Hapla This routine is only relevant for meshes that are fully interpolated across all ranks. 932645da879fSVaclav Hapla It will error out if a partially interpolated mesh is given on some rank. 932745da879fSVaclav Hapla It will do nothing for locally uninterpolated mesh (as there is nothing to check). 93289bf0dad6SMatthew G. Knepley 9329a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 933095eb5ee5SVaclav Hapla 93311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()` 93329bf0dad6SMatthew G. Knepley @*/ 9333d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) 9334d71ae5a4SJacob Faibussowitsch { 9335ab91121cSMatthew G. Knepley PetscInt dim, depth, vStart, vEnd, cStart, cEnd, c, h; 9336899ea2b8SJacob Faibussowitsch DMPlexInterpolatedFlag interpEnum; 93379bf0dad6SMatthew G. Knepley 93389bf0dad6SMatthew G. Knepley PetscFunctionBegin; 93399bf0dad6SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 93408f6815adSVaclav Hapla PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum)); 93413ba16761SJacob Faibussowitsch if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS); 93428f6815adSVaclav Hapla if (interpEnum != DMPLEX_INTERPOLATED_FULL) { 93433ba16761SJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported")); 93443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9345899ea2b8SJacob Faibussowitsch } 9346899ea2b8SJacob Faibussowitsch 93479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 93489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 93499566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9350ab91121cSMatthew G. Knepley for (h = cellHeight; h < PetscMin(depth, dim); ++h) { 93519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd)); 93523554e41dSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9353412e9a14SMatthew G. Knepley const PetscInt *cone, *ornt, *faceSizes, *faces; 9354412e9a14SMatthew G. Knepley const DMPolytopeType *faceTypes; 9355ba2698f1SMatthew G. Knepley DMPolytopeType ct; 9356412e9a14SMatthew G. Knepley PetscInt numFaces, coneSize, f; 9357412e9a14SMatthew G. Knepley PetscInt *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit; 93589bf0dad6SMatthew G. Knepley 93599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 93609566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9361412e9a14SMatthew G. Knepley if (unsplit) continue; 93629566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 93639566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 93649566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, c, &ornt)); 93659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 93669bf0dad6SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 93679bf0dad6SMatthew G. Knepley const PetscInt p = closure[cl]; 93689bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 93699bf0dad6SMatthew G. Knepley } 93709566063dSJacob Faibussowitsch PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 937163a3b9bcSJacob 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); 93729bf0dad6SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 9373d4961f80SStefano Zampini DMPolytopeType fct; 93749bf0dad6SMatthew G. Knepley PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 93759bf0dad6SMatthew G. Knepley 93769566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, cone[f], &fct)); 93779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure)); 93789bf0dad6SMatthew G. Knepley for (cl = 0; cl < fclosureSize * 2; cl += 2) { 93799bf0dad6SMatthew G. Knepley const PetscInt p = fclosure[cl]; 93809bf0dad6SMatthew G. Knepley if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 93819bf0dad6SMatthew G. Knepley } 938263a3b9bcSJacob 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]); 93839bf0dad6SMatthew G. Knepley for (v = 0; v < fnumCorners; ++v) { 9384b5a892a1SMatthew G. Knepley if (fclosure[v] != faces[fOff + v]) { 9385b5a892a1SMatthew G. Knepley PetscInt v1; 9386b5a892a1SMatthew G. Knepley 93879566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:")); 938863a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1])); 93899566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:")); 939063a3b9bcSJacob Faibussowitsch for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1])); 93919566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 939263a3b9bcSJacob 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]); 9393b5a892a1SMatthew G. Knepley } 93949bf0dad6SMatthew G. Knepley } 93959566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure)); 9396412e9a14SMatthew G. Knepley fOff += faceSizes[f]; 93979bf0dad6SMatthew G. Knepley } 93989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces)); 93999566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 94009bf0dad6SMatthew G. Knepley } 94013554e41dSMatthew G. Knepley } 94023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9403552f7358SJed Brown } 94043913d7c8SMatthew G. Knepley 9405bb6a34a8SMatthew G. Knepley /*@ 9406bb6a34a8SMatthew G. Knepley DMPlexCheckGeometry - Check the geometry of mesh cells 9407bb6a34a8SMatthew G. Knepley 9408bb6a34a8SMatthew G. Knepley Input Parameter: 9409a1cb98faSBarry Smith . dm - The `DMPLEX` object 9410a1cb98faSBarry Smith 9411a1cb98faSBarry Smith Level: developer 9412bb6a34a8SMatthew G. Knepley 941395eb5ee5SVaclav Hapla Notes: 941495eb5ee5SVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 941595eb5ee5SVaclav Hapla 941620f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9417bb6a34a8SMatthew G. Knepley 94181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 9419bb6a34a8SMatthew G. Knepley @*/ 9420d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm) 9421d71ae5a4SJacob Faibussowitsch { 9422a2a9e04cSMatthew G. Knepley Vec coordinates; 9423bb6a34a8SMatthew G. Knepley PetscReal detJ, J[9], refVol = 1.0; 9424bb6a34a8SMatthew G. Knepley PetscReal vol; 942551a74b61SMatthew G. Knepley PetscInt dim, depth, dE, d, cStart, cEnd, c; 9426bb6a34a8SMatthew G. Knepley 9427bb6a34a8SMatthew G. Knepley PetscFunctionBegin; 94289566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 94299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 94303ba16761SJacob Faibussowitsch if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS); 94319566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9432bb6a34a8SMatthew G. Knepley for (d = 0; d < dim; ++d) refVol *= 2.0; 94339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9434a2a9e04cSMatthew G. Knepley /* Make sure local coordinates are created, because that step is collective */ 94359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 94363ba16761SJacob Faibussowitsch if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS); 9437412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 9438412e9a14SMatthew G. Knepley DMPolytopeType ct; 9439412e9a14SMatthew G. Knepley PetscInt unsplit; 9440412e9a14SMatthew G. Knepley PetscBool ignoreZeroVol = PETSC_FALSE; 9441412e9a14SMatthew G. Knepley 94429566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, c, &ct)); 9443412e9a14SMatthew G. Knepley switch (ct) { 9444412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 9445412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9446d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9447d71ae5a4SJacob Faibussowitsch ignoreZeroVol = PETSC_TRUE; 9448d71ae5a4SJacob Faibussowitsch break; 9449d71ae5a4SJacob Faibussowitsch default: 9450d71ae5a4SJacob Faibussowitsch break; 9451412e9a14SMatthew G. Knepley } 9452412e9a14SMatthew G. Knepley switch (ct) { 9453412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM: 9454412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 9455412e9a14SMatthew G. Knepley case DM_POLYTOPE_QUAD_PRISM_TENSOR: 9456d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_PYRAMID: 9457d71ae5a4SJacob Faibussowitsch continue; 9458d71ae5a4SJacob Faibussowitsch default: 9459d71ae5a4SJacob Faibussowitsch break; 9460412e9a14SMatthew G. Knepley } 94619566063dSJacob Faibussowitsch PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit)); 9462412e9a14SMatthew G. Knepley if (unsplit) continue; 94639566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ)); 94641dca8a05SBarry 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); 946563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol))); 94666858538eSMatthew G. Knepley /* This should work with periodicity since DG coordinates should be used */ 94676858538eSMatthew G. Knepley if (depth > 1) { 94689566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL)); 94691dca8a05SBarry 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); 947063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol)); 9471bb6a34a8SMatthew G. Knepley } 9472bb6a34a8SMatthew G. Knepley } 94733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9474bb6a34a8SMatthew G. Knepley } 9475bb6a34a8SMatthew G. Knepley 947603da9461SVaclav Hapla /*@ 947720f4b53cSBarry Smith DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex. 94787726db96SVaclav Hapla 947920f4b53cSBarry Smith Collective 948003da9461SVaclav Hapla 948103da9461SVaclav Hapla Input Parameters: 9482a1cb98faSBarry Smith + dm - The `DMPLEX` object 948320f4b53cSBarry Smith . pointSF - The `PetscSF`, or `NULL` for `PointSF` attached to `DM` 9484a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM` 9485a1cb98faSBarry Smith 9486a1cb98faSBarry Smith Level: developer 948703da9461SVaclav Hapla 9488e83a0d2dSVaclav Hapla Notes: 9489e83a0d2dSVaclav Hapla This is mainly intended for debugging/testing purposes. 949003da9461SVaclav Hapla 9491a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 949295eb5ee5SVaclav Hapla 9493baca6076SPierre Jolivet Extra roots can come from periodic cuts, where additional points appear on the boundary 9494d7d32a9aSMatthew G. Knepley 94951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()` 949603da9461SVaclav Hapla @*/ 9497d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) 9498d71ae5a4SJacob Faibussowitsch { 94997726db96SVaclav Hapla PetscInt l, nleaves, nroots, overlap; 95007726db96SVaclav Hapla const PetscInt *locals; 95017726db96SVaclav Hapla const PetscSFNode *remotes; 9502f0cfc026SVaclav Hapla PetscBool distributed; 95037726db96SVaclav Hapla MPI_Comm comm; 95047726db96SVaclav Hapla PetscMPIInt rank; 950503da9461SVaclav Hapla 950603da9461SVaclav Hapla PetscFunctionBegin; 950703da9461SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 95087726db96SVaclav Hapla if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2); 95097726db96SVaclav Hapla else pointSF = dm->sf; 95107726db96SVaclav Hapla PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 95117726db96SVaclav Hapla PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached"); 95127726db96SVaclav Hapla PetscCallMPI(MPI_Comm_rank(comm, &rank)); 95137726db96SVaclav Hapla { 95147726db96SVaclav Hapla PetscMPIInt mpiFlag; 95157726db96SVaclav Hapla 95167726db96SVaclav Hapla PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag)); 95177726db96SVaclav 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); 95187726db96SVaclav Hapla } 95197726db96SVaclav Hapla PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes)); 95209566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 95217726db96SVaclav Hapla if (!distributed) { 95227726db96SVaclav 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); 95233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95248918e3e2SVaclav Hapla } 95257726db96SVaclav 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); 95267726db96SVaclav Hapla PetscCall(DMPlexGetOverlap(dm, &overlap)); 952703da9461SVaclav Hapla 95287726db96SVaclav Hapla /* Check SF graph is compatible with DMPlex chart */ 95297726db96SVaclav Hapla { 95307726db96SVaclav Hapla PetscInt pStart, pEnd, maxLeaf; 95317726db96SVaclav Hapla 95327726db96SVaclav Hapla PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 95337726db96SVaclav Hapla PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf)); 9534d7d32a9aSMatthew G. Knepley PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots); 95357726db96SVaclav Hapla PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd); 95367726db96SVaclav Hapla } 95377726db96SVaclav Hapla 95387726db96SVaclav Hapla /* Check Point SF has no local points referenced */ 95397726db96SVaclav Hapla for (l = 0; l < nleaves; l++) { 9540*6497c311SBarry Smith PetscAssert(remotes[l].rank != (PetscInt)rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%d,%" PetscInt_FMT ")", locals ? locals[l] : l, (PetscMPIInt)remotes[l].rank, remotes[l].index); 95417726db96SVaclav Hapla } 95427726db96SVaclav Hapla 95437726db96SVaclav Hapla /* Check there are no cells in interface */ 95447726db96SVaclav Hapla if (!overlap) { 95457726db96SVaclav Hapla PetscInt cellHeight, cStart, cEnd; 95467726db96SVaclav Hapla 95479566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 95489566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9549f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 95507726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9551f5869d18SMatthew G. Knepley 95527726db96SVaclav Hapla PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point); 95537726db96SVaclav Hapla } 955403da9461SVaclav Hapla } 9555ece87651SVaclav Hapla 95567726db96SVaclav Hapla /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */ 95577726db96SVaclav Hapla { 95587726db96SVaclav Hapla const PetscInt *rootdegree; 95597726db96SVaclav Hapla 95607726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree)); 95617726db96SVaclav Hapla PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree)); 9562f5869d18SMatthew G. Knepley for (l = 0; l < nleaves; ++l) { 95637726db96SVaclav Hapla const PetscInt point = locals ? locals[l] : l; 9564f5869d18SMatthew G. Knepley const PetscInt *cone; 9565f5869d18SMatthew G. Knepley PetscInt coneSize, c, idx; 9566f5869d18SMatthew G. Knepley 95679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 95689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 9569f5869d18SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 9570f5869d18SMatthew G. Knepley if (!rootdegree[cone[c]]) { 95717726db96SVaclav Hapla if (locals) { 95729566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx)); 95737726db96SVaclav Hapla } else { 95747726db96SVaclav Hapla idx = (cone[c] < nleaves) ? cone[c] : -1; 95757726db96SVaclav Hapla } 957663a3b9bcSJacob 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]); 9577f5869d18SMatthew G. Knepley } 9578f5869d18SMatthew G. Knepley } 9579ece87651SVaclav Hapla } 95807726db96SVaclav Hapla } 95813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 958203da9461SVaclav Hapla } 958303da9461SVaclav Hapla 95847f9d8d6cSVaclav Hapla /*@ 9585217fe35eSMatthew G. Knepley DMPlexCheckOrphanVertices - Check that no vertices are disconnected from the mesh, unless the mesh only consists of disconnected vertices. 9586217fe35eSMatthew G. Knepley 9587217fe35eSMatthew G. Knepley Collective 9588217fe35eSMatthew G. Knepley 9589217fe35eSMatthew G. Knepley Input Parameter: 9590217fe35eSMatthew G. Knepley . dm - The `DMPLEX` object 9591217fe35eSMatthew G. Knepley 9592217fe35eSMatthew G. Knepley Level: developer 9593217fe35eSMatthew G. Knepley 9594217fe35eSMatthew G. Knepley Notes: 9595217fe35eSMatthew G. Knepley This is mainly intended for debugging/testing purposes. 9596217fe35eSMatthew G. Knepley 9597217fe35eSMatthew G. Knepley Other cell types which are disconnected would be caught by the symmetry and face checks. 9598217fe35eSMatthew G. Knepley 9599217fe35eSMatthew G. Knepley For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9600217fe35eSMatthew G. Knepley 9601217fe35eSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheck()`, `DMSetFromOptions()` 9602217fe35eSMatthew G. Knepley @*/ 9603217fe35eSMatthew G. Knepley PetscErrorCode DMPlexCheckOrphanVertices(DM dm) 9604217fe35eSMatthew G. Knepley { 9605217fe35eSMatthew G. Knepley PetscInt pStart, pEnd, vStart, vEnd; 9606217fe35eSMatthew G. Knepley 9607217fe35eSMatthew G. Knepley PetscFunctionBegin; 9608217fe35eSMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9609217fe35eSMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9610217fe35eSMatthew G. Knepley if (pStart == vStart && pEnd == vEnd) PetscFunctionReturn(PETSC_SUCCESS); 9611217fe35eSMatthew G. Knepley for (PetscInt v = vStart; v < vEnd; ++v) { 9612217fe35eSMatthew G. Knepley PetscInt suppSize; 9613217fe35eSMatthew G. Knepley 9614217fe35eSMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, v, &suppSize)); 9615217fe35eSMatthew G. Knepley PetscCheck(suppSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is disconnected from the mesh", v); 9616217fe35eSMatthew G. Knepley } 9617217fe35eSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 9618217fe35eSMatthew G. Knepley } 9619217fe35eSMatthew G. Knepley 9620217fe35eSMatthew G. Knepley /*@ 962120f4b53cSBarry Smith DMPlexCheck - Perform various checks of `DMPLEX` sanity 96227f9d8d6cSVaclav Hapla 96237f9d8d6cSVaclav Hapla Input Parameter: 9624a1cb98faSBarry Smith . dm - The `DMPLEX` object 9625a1cb98faSBarry Smith 9626a1cb98faSBarry Smith Level: developer 96277f9d8d6cSVaclav Hapla 96287f9d8d6cSVaclav Hapla Notes: 96297f9d8d6cSVaclav Hapla This is a useful diagnostic when creating meshes programmatically. 96307f9d8d6cSVaclav Hapla 963120f4b53cSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 96327f9d8d6cSVaclav Hapla 963320f4b53cSBarry Smith Currently does not include `DMPlexCheckCellShape()`. 96347f9d8d6cSVaclav Hapla 96351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()` 96367f9d8d6cSVaclav Hapla @*/ 9637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm) 9638d71ae5a4SJacob Faibussowitsch { 96397f9d8d6cSVaclav Hapla PetscInt cellHeight; 96407f9d8d6cSVaclav Hapla 9641b5a892a1SMatthew G. Knepley PetscFunctionBegin; 96427f9d8d6cSVaclav Hapla PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 96439566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSymmetry(dm)); 96449566063dSJacob Faibussowitsch PetscCall(DMPlexCheckSkeleton(dm, cellHeight)); 96459566063dSJacob Faibussowitsch PetscCall(DMPlexCheckFaces(dm, cellHeight)); 96469566063dSJacob Faibussowitsch PetscCall(DMPlexCheckGeometry(dm)); 9647d7d32a9aSMatthew G. Knepley PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 96489566063dSJacob Faibussowitsch PetscCall(DMPlexCheckInterfaceCones(dm)); 9649217fe35eSMatthew G. Knepley PetscCall(DMPlexCheckOrphanVertices(dm)); 96503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9651b5a892a1SMatthew G. Knepley } 9652b5a892a1SMatthew G. Knepley 96539371c9d4SSatish Balay typedef struct cell_stats { 9654068a5610SStefano Zampini PetscReal min, max, sum, squaresum; 9655068a5610SStefano Zampini PetscInt count; 9656068a5610SStefano Zampini } cell_stats_t; 9657068a5610SStefano Zampini 9658d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) 9659d71ae5a4SJacob Faibussowitsch { 9660068a5610SStefano Zampini PetscInt i, N = *len; 9661068a5610SStefano Zampini 9662068a5610SStefano Zampini for (i = 0; i < N; i++) { 9663068a5610SStefano Zampini cell_stats_t *A = (cell_stats_t *)a; 9664068a5610SStefano Zampini cell_stats_t *B = (cell_stats_t *)b; 9665068a5610SStefano Zampini 9666068a5610SStefano Zampini B->min = PetscMin(A->min, B->min); 9667068a5610SStefano Zampini B->max = PetscMax(A->max, B->max); 9668068a5610SStefano Zampini B->sum += A->sum; 9669068a5610SStefano Zampini B->squaresum += A->squaresum; 9670068a5610SStefano Zampini B->count += A->count; 9671068a5610SStefano Zampini } 9672068a5610SStefano Zampini } 9673068a5610SStefano Zampini 9674068a5610SStefano Zampini /*@ 967543fa8764SMatthew G. Knepley DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics. 9676068a5610SStefano Zampini 967720f4b53cSBarry Smith Collective 96788261a58bSMatthew G. Knepley 9679068a5610SStefano Zampini Input Parameters: 9680a1cb98faSBarry Smith + dm - The `DMPLEX` object 968120f4b53cSBarry Smith . output - If true, statistics will be displayed on `stdout` 9682a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output 9683a1cb98faSBarry Smith 9684a1cb98faSBarry Smith Level: developer 9685068a5610SStefano Zampini 968695eb5ee5SVaclav Hapla Notes: 968795eb5ee5SVaclav Hapla This is mainly intended for debugging/testing purposes. 968895eb5ee5SVaclav Hapla 9689a1cb98faSBarry Smith For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`. 9690068a5610SStefano Zampini 96911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()` 9692068a5610SStefano Zampini @*/ 9693d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) 9694d71ae5a4SJacob Faibussowitsch { 9695068a5610SStefano Zampini DM dmCoarse; 969643fa8764SMatthew G. Knepley cell_stats_t stats, globalStats; 969743fa8764SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 969843fa8764SMatthew G. Knepley PetscReal *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0; 969943fa8764SMatthew G. Knepley PetscReal limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL; 9700412e9a14SMatthew G. Knepley PetscInt cdim, cStart, cEnd, c, eStart, eEnd, count = 0; 970143fa8764SMatthew G. Knepley PetscMPIInt rank, size; 9702068a5610SStefano Zampini 9703068a5610SStefano Zampini PetscFunctionBegin; 9704068a5610SStefano Zampini PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9705068a5610SStefano Zampini stats.min = PETSC_MAX_REAL; 9706068a5610SStefano Zampini stats.max = PETSC_MIN_REAL; 9707068a5610SStefano Zampini stats.sum = stats.squaresum = 0.; 9708068a5610SStefano Zampini stats.count = 0; 9709068a5610SStefano Zampini 97109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 97119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 97129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 97139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ)); 97149566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 97159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 9716412e9a14SMatthew G. Knepley for (c = cStart; c < cEnd; c++) { 9717068a5610SStefano Zampini PetscInt i; 9718068a5610SStefano Zampini PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ; 9719068a5610SStefano Zampini 97209566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ)); 972163a3b9bcSJacob Faibussowitsch PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c); 972243fa8764SMatthew G. Knepley for (i = 0; i < PetscSqr(cdim); ++i) { 9723068a5610SStefano Zampini frobJ += J[i] * J[i]; 9724068a5610SStefano Zampini frobInvJ += invJ[i] * invJ[i]; 9725068a5610SStefano Zampini } 9726068a5610SStefano Zampini cond2 = frobJ * frobInvJ; 9727068a5610SStefano Zampini cond = PetscSqrtReal(cond2); 9728068a5610SStefano Zampini 9729068a5610SStefano Zampini stats.min = PetscMin(stats.min, cond); 9730068a5610SStefano Zampini stats.max = PetscMax(stats.max, cond); 9731068a5610SStefano Zampini stats.sum += cond; 9732068a5610SStefano Zampini stats.squaresum += cond2; 9733068a5610SStefano Zampini stats.count++; 97348261a58bSMatthew G. Knepley if (output && cond > limit) { 973543fa8764SMatthew G. Knepley PetscSection coordSection; 973643fa8764SMatthew G. Knepley Vec coordsLocal; 973743fa8764SMatthew G. Knepley PetscScalar *coords = NULL; 973843fa8764SMatthew G. Knepley PetscInt Nv, d, clSize, cl, *closure = NULL; 973943fa8764SMatthew G. Knepley 97409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 97419566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 97429566063dSJacob Faibussowitsch PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 974363a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond)); 974443fa8764SMatthew G. Knepley for (i = 0; i < Nv / cdim; ++i) { 974563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ": (", i)); 974643fa8764SMatthew G. Knepley for (d = 0; d < cdim; ++d) { 97479566063dSJacob Faibussowitsch if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", ")); 97489566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d]))); 974943fa8764SMatthew G. Knepley } 97509566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, ")\n")); 975143fa8764SMatthew G. Knepley } 97529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 975343fa8764SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 975443fa8764SMatthew G. Knepley const PetscInt edge = closure[cl]; 975543fa8764SMatthew G. Knepley 975643fa8764SMatthew G. Knepley if ((edge >= eStart) && (edge < eEnd)) { 975743fa8764SMatthew G. Knepley PetscReal len; 975843fa8764SMatthew G. Knepley 97599566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL)); 976063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT ": length %g\n", edge, (double)len)); 976143fa8764SMatthew G. Knepley } 976243fa8764SMatthew G. Knepley } 97639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 97649566063dSJacob Faibussowitsch PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords)); 976543fa8764SMatthew G. Knepley } 9766068a5610SStefano Zampini } 97679566063dSJacob Faibussowitsch if (output) PetscCall(PetscSynchronizedFlush(comm, NULL)); 9768068a5610SStefano Zampini 9769068a5610SStefano Zampini if (size > 1) { 9770068a5610SStefano Zampini PetscMPIInt blockLengths[2] = {4, 1}; 9771068a5610SStefano Zampini MPI_Aint blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)}; 9772068a5610SStefano Zampini MPI_Datatype blockTypes[2] = {MPIU_REAL, MPIU_INT}, statType; 9773068a5610SStefano Zampini MPI_Op statReduce; 9774068a5610SStefano Zampini 97759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType)); 97769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&statType)); 97779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce)); 97789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm)); 97799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Op_free(&statReduce)); 97809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&statType)); 9781068a5610SStefano Zampini } else { 97829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&globalStats, &stats, 1)); 9783068a5610SStefano Zampini } 9784dd400576SPatrick Sanan if (rank == 0) { 9785068a5610SStefano Zampini count = globalStats.count; 9786068a5610SStefano Zampini min = globalStats.min; 9787068a5610SStefano Zampini max = globalStats.max; 9788068a5610SStefano Zampini mean = globalStats.sum / globalStats.count; 9789068a5610SStefano Zampini stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0; 9790068a5610SStefano Zampini } 9791068a5610SStefano Zampini 979248a46eb9SPierre 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)); 97939566063dSJacob Faibussowitsch PetscCall(PetscFree2(J, invJ)); 9794068a5610SStefano Zampini 97959566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &dmCoarse)); 9796068a5610SStefano Zampini if (dmCoarse) { 9797068a5610SStefano Zampini PetscBool isplex; 9798068a5610SStefano Zampini 97999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex)); 98001baa6e33SBarry Smith if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit)); 9801068a5610SStefano Zampini } 98023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9803068a5610SStefano Zampini } 9804068a5610SStefano Zampini 9805f108dbd7SJacob Faibussowitsch /*@ 9806f108dbd7SJacob Faibussowitsch DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with 9807f108dbd7SJacob Faibussowitsch orthogonal quality below given tolerance. 9808f108dbd7SJacob Faibussowitsch 980920f4b53cSBarry Smith Collective 9810f108dbd7SJacob Faibussowitsch 9811f108dbd7SJacob Faibussowitsch Input Parameters: 9812a1cb98faSBarry Smith + dm - The `DMPLEX` object 9813a1cb98faSBarry Smith . fv - Optional `PetscFV` object for pre-computed cell/face centroid information 9814f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells. 9815f108dbd7SJacob Faibussowitsch 9816f108dbd7SJacob Faibussowitsch Output Parameters: 981720f4b53cSBarry Smith + OrthQual - `Vec` containing orthogonal quality per cell 9818a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE` 9819f108dbd7SJacob Faibussowitsch 9820f108dbd7SJacob Faibussowitsch Options Database Keys: 9821a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported. 9822f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector. 9823f108dbd7SJacob Faibussowitsch 9824a1cb98faSBarry Smith Level: intermediate 9825a1cb98faSBarry Smith 9826f108dbd7SJacob Faibussowitsch Notes: 9827a4e35b19SJacob Faibussowitsch Orthogonal quality is given by the following formula\: 9828f108dbd7SJacob Faibussowitsch 9829a1cb98faSBarry Smith $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$ 9830f108dbd7SJacob Faibussowitsch 9831f108dbd7SJacob 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 9832f108dbd7SJacob Faibussowitsch is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the 9833f108dbd7SJacob Faibussowitsch current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by 9834f108dbd7SJacob Faibussowitsch calculating the cosine of the angle between these vectors. 9835f108dbd7SJacob Faibussowitsch 9836f108dbd7SJacob Faibussowitsch Orthogonal quality ranges from 1 (best) to 0 (worst). 9837f108dbd7SJacob Faibussowitsch 9838a1cb98faSBarry Smith This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for 9839f108dbd7SJacob Faibussowitsch pre-computed FVM cell data, but if it is not passed in then this data will be computed. 9840f108dbd7SJacob Faibussowitsch 9841f108dbd7SJacob Faibussowitsch Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance. 9842f108dbd7SJacob Faibussowitsch 98431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec` 9844f108dbd7SJacob Faibussowitsch @*/ 9845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) 9846d71ae5a4SJacob Faibussowitsch { 98476ed19f2fSJacob Faibussowitsch PetscInt nc, cellHeight, cStart, cEnd, cell, cellIter = 0; 98486ed19f2fSJacob Faibussowitsch PetscInt *idx; 98496ed19f2fSJacob Faibussowitsch PetscScalar *oqVals; 9850f108dbd7SJacob Faibussowitsch const PetscScalar *cellGeomArr, *faceGeomArr; 98516ed19f2fSJacob Faibussowitsch PetscReal *ci, *fi, *Ai; 9852f108dbd7SJacob Faibussowitsch MPI_Comm comm; 9853f108dbd7SJacob Faibussowitsch Vec cellgeom, facegeom; 9854f108dbd7SJacob Faibussowitsch DM dmFace, dmCell; 9855f108dbd7SJacob Faibussowitsch IS glob; 9856f108dbd7SJacob Faibussowitsch ISLocalToGlobalMapping ltog; 9857f108dbd7SJacob Faibussowitsch PetscViewer vwr; 9858f108dbd7SJacob Faibussowitsch 9859f108dbd7SJacob Faibussowitsch PetscFunctionBegin; 9860f108dbd7SJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9861ad540459SPierre Jolivet if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2); 98624f572ea9SToby Isaac PetscAssertPointer(OrthQual, 4); 98636bdcaf15SBarry Smith PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol); 98649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 98659566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &nc)); 986663a3b9bcSJacob Faibussowitsch PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc); 98676ed19f2fSJacob Faibussowitsch { 98686ed19f2fSJacob Faibussowitsch DMPlexInterpolatedFlag interpFlag; 98696ed19f2fSJacob Faibussowitsch 98709566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpFlag)); 9871f108dbd7SJacob Faibussowitsch if (interpFlag != DMPLEX_INTERPOLATED_FULL) { 9872f108dbd7SJacob Faibussowitsch PetscMPIInt rank; 9873f108dbd7SJacob Faibussowitsch 98749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 987598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank); 9876f108dbd7SJacob Faibussowitsch } 98776ed19f2fSJacob Faibussowitsch } 9878f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 98794f572ea9SToby Isaac PetscAssertPointer(OrthQualLabel, 5); 98809566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Orthogonal_Quality")); 98819566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel)); 98829371c9d4SSatish Balay } else { 98839371c9d4SSatish Balay *OrthQualLabel = NULL; 98849371c9d4SSatish Balay } 98859566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight)); 98869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 9887e2b8d0fcSMatthew G. Knepley PetscCall(DMPlexCreateCellNumbering(dm, PETSC_TRUE, &glob)); 98889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(glob, <og)); 98899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH)); 98909566063dSJacob Faibussowitsch PetscCall(VecCreate(comm, OrthQual)); 98919566063dSJacob Faibussowitsch PetscCall(VecSetType(*OrthQual, VECSTANDARD)); 98929566063dSJacob Faibussowitsch PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE)); 98939566063dSJacob Faibussowitsch PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog)); 98949566063dSJacob Faibussowitsch PetscCall(VecSetUp(*OrthQual)); 98959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&glob)); 98969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(<og)); 98979566063dSJacob Faibussowitsch PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL)); 98989566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr)); 98999566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(facegeom, &faceGeomArr)); 99009566063dSJacob Faibussowitsch PetscCall(VecGetDM(cellgeom, &dmCell)); 99019566063dSJacob Faibussowitsch PetscCall(VecGetDM(facegeom, &dmFace)); 99029566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai)); 99036ed19f2fSJacob Faibussowitsch for (cell = cStart; cell < cEnd; cellIter++, cell++) { 99046ed19f2fSJacob Faibussowitsch PetscInt cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE; 9905f108dbd7SJacob Faibussowitsch PetscInt cellarr[2], *adj = NULL; 9906f108dbd7SJacob Faibussowitsch PetscScalar *cArr, *fArr; 9907898cd552SSatish Balay PetscReal minvalc = 1.0, minvalf = 1.0; 9908f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cg; 9909f108dbd7SJacob Faibussowitsch 99106ed19f2fSJacob Faibussowitsch idx[cellIter] = cell - cStart; 9911f108dbd7SJacob Faibussowitsch cellarr[0] = cell; 9912f108dbd7SJacob Faibussowitsch /* Make indexing into cellGeom easier */ 99139566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg)); 99149566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj)); 9915f108dbd7SJacob Faibussowitsch /* Technically 1 too big, but easier than fiddling with empty adjacency array */ 99169566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr)); 99176ed19f2fSJacob Faibussowitsch for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) { 99186ed19f2fSJacob Faibussowitsch PetscInt i; 99196ed19f2fSJacob Faibussowitsch const PetscInt neigh = adj[cellneigh]; 9920f108dbd7SJacob Faibussowitsch PetscReal normci = 0, normfi = 0, normai = 0; 9921f108dbd7SJacob Faibussowitsch PetscFVCellGeom *cgneigh; 9922f108dbd7SJacob Faibussowitsch PetscFVFaceGeom *fg; 9923f108dbd7SJacob Faibussowitsch 9924f108dbd7SJacob Faibussowitsch /* Don't count ourselves in the neighbor list */ 9925f108dbd7SJacob Faibussowitsch if (neigh == cell) continue; 99269566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh)); 9927f108dbd7SJacob Faibussowitsch cellarr[1] = neigh; 99286ed19f2fSJacob Faibussowitsch { 99296ed19f2fSJacob Faibussowitsch PetscInt numcovpts; 99306ed19f2fSJacob Faibussowitsch const PetscInt *covpts; 99316ed19f2fSJacob Faibussowitsch 99329566063dSJacob Faibussowitsch PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts)); 99339566063dSJacob Faibussowitsch PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg)); 99349566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts)); 99356ed19f2fSJacob Faibussowitsch } 9936f108dbd7SJacob Faibussowitsch 9937f108dbd7SJacob Faibussowitsch /* Compute c_i, f_i and their norms */ 9938f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9939f108dbd7SJacob Faibussowitsch ci[i] = cgneigh->centroid[i] - cg->centroid[i]; 9940f108dbd7SJacob Faibussowitsch fi[i] = fg->centroid[i] - cg->centroid[i]; 9941f108dbd7SJacob Faibussowitsch Ai[i] = fg->normal[i]; 9942addd1e01SJunchao Zhang normci += PetscPowReal(ci[i], 2); 9943addd1e01SJunchao Zhang normfi += PetscPowReal(fi[i], 2); 9944addd1e01SJunchao Zhang normai += PetscPowReal(Ai[i], 2); 9945f108dbd7SJacob Faibussowitsch } 9946addd1e01SJunchao Zhang normci = PetscSqrtReal(normci); 9947addd1e01SJunchao Zhang normfi = PetscSqrtReal(normfi); 9948addd1e01SJunchao Zhang normai = PetscSqrtReal(normai); 9949f108dbd7SJacob Faibussowitsch 9950f108dbd7SJacob Faibussowitsch /* Normalize and compute for each face-cell-normal pair */ 9951f108dbd7SJacob Faibussowitsch for (i = 0; i < nc; i++) { 9952f108dbd7SJacob Faibussowitsch ci[i] = ci[i] / normci; 9953f108dbd7SJacob Faibussowitsch fi[i] = fi[i] / normfi; 9954f108dbd7SJacob Faibussowitsch Ai[i] = Ai[i] / normai; 9955f108dbd7SJacob Faibussowitsch /* PetscAbs because I don't know if normals are guaranteed to point out */ 9956f108dbd7SJacob Faibussowitsch cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]); 9957f108dbd7SJacob Faibussowitsch fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]); 9958f108dbd7SJacob Faibussowitsch } 9959ad540459SPierre Jolivet if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]); 9960ad540459SPierre Jolivet if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]); 9961f108dbd7SJacob Faibussowitsch } 99629566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 99639566063dSJacob Faibussowitsch PetscCall(PetscFree2(cArr, fArr)); 9964f108dbd7SJacob Faibussowitsch /* Defer to cell if they're equal */ 99656ed19f2fSJacob Faibussowitsch oqVals[cellIter] = PetscMin(minvalf, minvalc); 9966f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 99679566063dSJacob Faibussowitsch if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE)); 9968f108dbd7SJacob Faibussowitsch } 9969f108dbd7SJacob Faibussowitsch } 99709566063dSJacob Faibussowitsch PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES)); 99719566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(*OrthQual)); 99729566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(*OrthQual)); 99739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr)); 99749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr)); 9975648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL)); 9976f108dbd7SJacob Faibussowitsch if (OrthQualLabel) { 99779566063dSJacob Faibussowitsch if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr)); 9978f108dbd7SJacob Faibussowitsch } 99799566063dSJacob Faibussowitsch PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai)); 9980648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&vwr)); 99819566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view")); 99823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9983f108dbd7SJacob Faibussowitsch } 9984f108dbd7SJacob Faibussowitsch 9985d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect 99861eb70e55SToby Isaac * interpolator construction */ 9987d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm) 9988d71ae5a4SJacob Faibussowitsch { 99891eb70e55SToby Isaac PetscSection section, newSection, gsection; 99901eb70e55SToby Isaac PetscSF sf; 99911eb70e55SToby Isaac PetscBool hasConstraints, ghasConstraints; 99921eb70e55SToby Isaac 99931eb70e55SToby Isaac PetscFunctionBegin; 99941eb70e55SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 99954f572ea9SToby Isaac PetscAssertPointer(odm, 2); 99969566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 99979566063dSJacob Faibussowitsch PetscCall(PetscSectionHasConstraints(section, &hasConstraints)); 9998712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 99991eb70e55SToby Isaac if (!ghasConstraints) { 100009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)dm)); 100011eb70e55SToby Isaac *odm = dm; 100023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100031eb70e55SToby Isaac } 100049566063dSJacob Faibussowitsch PetscCall(DMClone(dm, odm)); 10005bb4b53efSMatthew G. Knepley PetscCall(DMCopyFields(dm, PETSC_DETERMINE, PETSC_DETERMINE, *odm)); 100069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(*odm, &newSection)); 100079566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(*odm, &sf)); 10008eb9d3e4dSMatthew G. Knepley PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_TRUE, PETSC_FALSE, &gsection)); 100099566063dSJacob Faibussowitsch PetscCall(DMSetGlobalSection(*odm, gsection)); 100109566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&gsection)); 100113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100121eb70e55SToby Isaac } 100131eb70e55SToby Isaac 10014d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) 10015d71ae5a4SJacob Faibussowitsch { 100161eb70e55SToby Isaac DM dmco, dmfo; 100171eb70e55SToby Isaac Mat interpo; 100181eb70e55SToby Isaac Vec rscale; 100191eb70e55SToby Isaac Vec cglobalo, clocal; 100201eb70e55SToby Isaac Vec fglobal, fglobalo, flocal; 100211eb70e55SToby Isaac PetscBool regular; 100221eb70e55SToby Isaac 100231eb70e55SToby Isaac PetscFunctionBegin; 100249566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmc, &dmco)); 100259566063dSJacob Faibussowitsch PetscCall(DMGetFullDM(dmf, &dmfo)); 100269566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dmfo, dmco)); 100279566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmf, ®ular)); 100289566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dmfo, regular)); 100299566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale)); 100309566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmco, &cglobalo)); 100319566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmc, &clocal)); 100329566063dSJacob Faibussowitsch PetscCall(VecSet(cglobalo, 0.)); 100339566063dSJacob Faibussowitsch PetscCall(VecSet(clocal, 0.)); 100349566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmf, &fglobal)); 100359566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dmfo, &fglobalo)); 100369566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(dmf, &flocal)); 100379566063dSJacob Faibussowitsch PetscCall(VecSet(fglobal, 0.)); 100389566063dSJacob Faibussowitsch PetscCall(VecSet(fglobalo, 0.)); 100399566063dSJacob Faibussowitsch PetscCall(VecSet(flocal, 0.)); 100409566063dSJacob Faibussowitsch PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL)); 100419566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo)); 100429566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo)); 100439566063dSJacob Faibussowitsch PetscCall(MatMult(interpo, cglobalo, fglobalo)); 100449566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal)); 100459566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal)); 100469566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal)); 100479566063dSJacob Faibussowitsch PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal)); 100481eb70e55SToby Isaac *shift = fglobal; 100499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&flocal)); 100509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&fglobalo)); 100519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&clocal)); 100529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobalo)); 100539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 100549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interpo)); 100559566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmfo)); 100569566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmco)); 100573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100581eb70e55SToby Isaac } 100591eb70e55SToby Isaac 10060d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) 10061d71ae5a4SJacob Faibussowitsch { 100621eb70e55SToby Isaac PetscObject shifto; 100631eb70e55SToby Isaac Vec shift; 100641eb70e55SToby Isaac 100651eb70e55SToby Isaac PetscFunctionBegin; 100661eb70e55SToby Isaac if (!interp) { 100671eb70e55SToby Isaac Vec rscale; 100681eb70e55SToby Isaac 100699566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale)); 100709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rscale)); 100711eb70e55SToby Isaac } else { 100729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)interp)); 100731eb70e55SToby Isaac } 100749566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto)); 100751eb70e55SToby Isaac if (!shifto) { 100769566063dSJacob Faibussowitsch PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift)); 100779566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift)); 100781eb70e55SToby Isaac shifto = (PetscObject)shift; 100799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&shift)); 100801eb70e55SToby Isaac } 100811eb70e55SToby Isaac shift = (Vec)shifto; 100829566063dSJacob Faibussowitsch PetscCall(MatInterpolate(interp, coarseSol, fineSol)); 100839566063dSJacob Faibussowitsch PetscCall(VecAXPY(fineSol, 1.0, shift)); 100849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&interp)); 100853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 100861eb70e55SToby Isaac } 100871eb70e55SToby Isaac 10088bceba477SMatthew G. Knepley /* Pointwise interpolation 10089bceba477SMatthew G. Knepley Just code FEM for now 10090bceba477SMatthew G. Knepley u^f = I u^c 100914ca5e9f5SMatthew G. Knepley sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 100924ca5e9f5SMatthew G. Knepley u^f_i = sum_j psi^f_i I phi^c_j u^c_j 100934ca5e9f5SMatthew G. Knepley I_{ij} = psi^f_i phi^c_j 10094bceba477SMatthew G. Knepley */ 10095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 10096d71ae5a4SJacob Faibussowitsch { 10097bceba477SMatthew G. Knepley PetscSection gsc, gsf; 10098bceba477SMatthew G. Knepley PetscInt m, n; 10099a063dac3SMatthew G. Knepley void *ctx; 1010068132eb9SMatthew G. Knepley DM cdm; 10101cf51de39SMatthew G. Knepley PetscBool regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE; 10102bceba477SMatthew G. Knepley 10103bceba477SMatthew G. Knepley PetscFunctionBegin; 101049566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 101059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 101069566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 101079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 1010868132eb9SMatthew G. Knepley 101099566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis)); 101109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation)); 101119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 101129566063dSJacob Faibussowitsch PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype)); 101139566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 1011468132eb9SMatthew G. Knepley 101159566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 101169566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 101179566063dSJacob Faibussowitsch if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx)); 101189566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx)); 101199566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view")); 101204db47ee9SStefano Zampini if (scaling) { 101215d1c2e58SMatthew G. Knepley /* Use naive scaling */ 101229566063dSJacob Faibussowitsch PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling)); 101234db47ee9SStefano Zampini } 101243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10125a063dac3SMatthew G. Knepley } 10126bceba477SMatthew G. Knepley 10127d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 10128d71ae5a4SJacob Faibussowitsch { 101296dbf9973SLawrence Mitchell VecScatter ctx; 1013090748bafSMatthew G. Knepley 10131a063dac3SMatthew G. Knepley PetscFunctionBegin; 101329566063dSJacob Faibussowitsch PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL)); 101339566063dSJacob Faibussowitsch PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat)); 101349566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&ctx)); 101353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10136bceba477SMatthew G. Knepley } 10137bceba477SMatthew G. Knepley 10138d71ae5a4SJacob 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[]) 10139d71ae5a4SJacob Faibussowitsch { 10140a102dd69SStefano Zampini const PetscInt f = (PetscInt)PetscRealPart(constants[numConstants]); 10141a102dd69SStefano Zampini const PetscInt Nc = uOff[f + 1] - uOff[f]; 10142a102dd69SStefano Zampini for (PetscInt c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0; 101433e9753d6SMatthew G. Knepley } 101443e9753d6SMatthew G. Knepley 101458e9849d2SStefano Zampini PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *lmass, Vec *mass) 10146d71ae5a4SJacob Faibussowitsch { 10147b4937a87SMatthew G. Knepley DM dmc; 10148b4937a87SMatthew G. Knepley PetscDS ds; 10149b4937a87SMatthew G. Knepley Vec ones, locmass; 10150b4937a87SMatthew G. Knepley IS cellIS; 10151b4937a87SMatthew G. Knepley PetscFormKey key; 10152b4937a87SMatthew G. Knepley PetscInt depth; 10153b4937a87SMatthew G. Knepley 10154b4937a87SMatthew G. Knepley PetscFunctionBegin; 101559566063dSJacob Faibussowitsch PetscCall(DMClone(dm, &dmc)); 101569566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, dmc)); 101579566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 10158a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 101598e9849d2SStefano Zampini if (mass) PetscCall(DMCreateGlobalVector(dm, mass)); 101608e9849d2SStefano Zampini if (lmass) PetscCall(DMCreateLocalVector(dm, &locmass)); 101618e9849d2SStefano Zampini else PetscCall(DMGetLocalVector(dm, &locmass)); 101628e9849d2SStefano Zampini PetscCall(DMGetLocalVector(dm, &ones)); 101638e9849d2SStefano Zampini PetscCall(DMPlexGetDepth(dm, &depth)); 101648e9849d2SStefano Zampini PetscCall(DMGetStratumIS(dm, "depth", depth, &cellIS)); 101659566063dSJacob Faibussowitsch PetscCall(VecSet(locmass, 0.0)); 101669566063dSJacob Faibussowitsch PetscCall(VecSet(ones, 1.0)); 10167b4937a87SMatthew G. Knepley key.label = NULL; 10168b4937a87SMatthew G. Knepley key.value = 0; 10169b4937a87SMatthew G. Knepley key.field = 0; 10170b4937a87SMatthew G. Knepley key.part = 0; 101719566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL)); 101729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 101738e9849d2SStefano Zampini if (mass) { 101748e9849d2SStefano Zampini PetscCall(DMLocalToGlobalBegin(dm, locmass, ADD_VALUES, *mass)); 101758e9849d2SStefano Zampini PetscCall(DMLocalToGlobalEnd(dm, locmass, ADD_VALUES, *mass)); 101768e9849d2SStefano Zampini } 101778e9849d2SStefano Zampini PetscCall(DMRestoreLocalVector(dm, &ones)); 101788e9849d2SStefano Zampini if (lmass) *lmass = locmass; 101798e9849d2SStefano Zampini else PetscCall(DMRestoreLocalVector(dm, &locmass)); 101809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 101813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10182b4937a87SMatthew G. Knepley } 10183b4937a87SMatthew G. Knepley 10184d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) 10185d71ae5a4SJacob Faibussowitsch { 10186bd041c0cSMatthew G. Knepley PetscSection gsc, gsf; 10187bd041c0cSMatthew G. Knepley PetscInt m, n; 10188bd041c0cSMatthew G. Knepley void *ctx; 10189bd041c0cSMatthew G. Knepley DM cdm; 10190bd041c0cSMatthew G. Knepley PetscBool regular; 10191bd041c0cSMatthew G. Knepley 10192bd041c0cSMatthew G. Knepley PetscFunctionBegin; 101933e9753d6SMatthew G. Knepley if (dmFine == dmCoarse) { 101943e9753d6SMatthew G. Knepley DM dmc; 101953e9753d6SMatthew G. Knepley PetscDS ds; 10196b4937a87SMatthew G. Knepley PetscWeakForm wf; 101973e9753d6SMatthew G. Knepley Vec u; 101983e9753d6SMatthew G. Knepley IS cellIS; 1019906ad1575SMatthew G. Knepley PetscFormKey key; 102003e9753d6SMatthew G. Knepley PetscInt depth; 102013e9753d6SMatthew G. Knepley 102029566063dSJacob Faibussowitsch PetscCall(DMClone(dmFine, &dmc)); 102039566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dmFine, dmc)); 102049566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmc, &ds)); 102059566063dSJacob Faibussowitsch PetscCall(PetscDSGetWeakForm(ds, &wf)); 102069566063dSJacob Faibussowitsch PetscCall(PetscWeakFormClear(wf)); 10207a102dd69SStefano Zampini for (PetscInt f = 0; f < dmc->Nf; ++f) PetscCall(PetscDSSetJacobian(ds, f, f, g0_identity_private, NULL, NULL, NULL)); 102089566063dSJacob Faibussowitsch PetscCall(DMCreateMatrix(dmc, mass)); 102098d94ca23SJed Brown PetscCall(DMGetLocalVector(dmc, &u)); 102109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmc, &depth)); 102119566063dSJacob Faibussowitsch PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS)); 102129566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*mass)); 102136528b96dSMatthew G. Knepley key.label = NULL; 102146528b96dSMatthew G. Knepley key.value = 0; 102156528b96dSMatthew G. Knepley key.field = 0; 1021606ad1575SMatthew G. Knepley key.part = 0; 102179566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL)); 102189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 102198d94ca23SJed Brown PetscCall(DMRestoreLocalVector(dmc, &u)); 102209566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 102213e9753d6SMatthew G. Knepley } else { 102229566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 102239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 102249566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmCoarse, &gsc)); 102259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n)); 10226bd041c0cSMatthew G. Knepley 102279566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 102289566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 102299566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 102309566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 10231bd041c0cSMatthew G. Knepley 102329566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmFine, &cdm)); 102339566063dSJacob Faibussowitsch PetscCall(DMPlexGetRegularRefinement(dmFine, ®ular)); 102349566063dSJacob Faibussowitsch if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx)); 102359566063dSJacob Faibussowitsch else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx)); 102363e9753d6SMatthew G. Knepley } 102379566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 102383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10239bd041c0cSMatthew G. Knepley } 10240bd041c0cSMatthew G. Knepley 102410aef6b92SMatthew G. Knepley /*@ 102420aef6b92SMatthew G. Knepley DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 102430aef6b92SMatthew G. Knepley 102440aef6b92SMatthew G. Knepley Input Parameter: 10245a1cb98faSBarry Smith . dm - The `DMPLEX` object 102460aef6b92SMatthew G. Knepley 102470aef6b92SMatthew G. Knepley Output Parameter: 102480aef6b92SMatthew G. Knepley . regular - The flag 102490aef6b92SMatthew G. Knepley 102500aef6b92SMatthew G. Knepley Level: intermediate 102510aef6b92SMatthew G. Knepley 102521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()` 102530aef6b92SMatthew G. Knepley @*/ 10254d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 10255d71ae5a4SJacob Faibussowitsch { 102560aef6b92SMatthew G. Knepley PetscFunctionBegin; 102570aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102584f572ea9SToby Isaac PetscAssertPointer(regular, 2); 102590aef6b92SMatthew G. Knepley *regular = ((DM_Plex *)dm->data)->regularRefinement; 102603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102610aef6b92SMatthew G. Knepley } 102620aef6b92SMatthew G. Knepley 102630aef6b92SMatthew G. Knepley /*@ 102640aef6b92SMatthew G. Knepley DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 102650aef6b92SMatthew G. Knepley 102660aef6b92SMatthew G. Knepley Input Parameters: 10267a1cb98faSBarry Smith + dm - The `DMPLEX` object 102680aef6b92SMatthew G. Knepley - regular - The flag 102690aef6b92SMatthew G. Knepley 102700aef6b92SMatthew G. Knepley Level: intermediate 102710aef6b92SMatthew G. Knepley 102721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()` 102730aef6b92SMatthew G. Knepley @*/ 10274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 10275d71ae5a4SJacob Faibussowitsch { 102760aef6b92SMatthew G. Knepley PetscFunctionBegin; 102770aef6b92SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 102780aef6b92SMatthew G. Knepley ((DM_Plex *)dm->data)->regularRefinement = regular; 102793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 102800aef6b92SMatthew G. Knepley } 102810aef6b92SMatthew G. Knepley 10282a68b90caSToby Isaac /*@ 10283f7c74593SToby Isaac DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 10284a1cb98faSBarry Smith call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`. 10285a68b90caSToby Isaac 10286a1cb98faSBarry Smith Not Collective 10287a68b90caSToby Isaac 10288f899ff85SJose E. Roman Input Parameter: 10289a1cb98faSBarry Smith . dm - The `DMPLEX` object 10290a68b90caSToby Isaac 10291a68b90caSToby Isaac Output Parameters: 1029220f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points. 1029320f4b53cSBarry Smith - anchorIS - If not `NULL`, set to the list of anchors indexed by `anchorSection` 10294a68b90caSToby Isaac 10295a68b90caSToby Isaac Level: intermediate 10296a68b90caSToby Isaac 102971cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection` 10298a68b90caSToby Isaac @*/ 10299d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 10300d71ae5a4SJacob Faibussowitsch { 10301a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10302a68b90caSToby Isaac 10303a68b90caSToby Isaac PetscFunctionBegin; 10304a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103059566063dSJacob Faibussowitsch if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm)); 10306a68b90caSToby Isaac if (anchorSection) *anchorSection = plex->anchorSection; 10307a68b90caSToby Isaac if (anchorIS) *anchorIS = plex->anchorIS; 103083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10309a68b90caSToby Isaac } 10310a68b90caSToby Isaac 10311a68b90caSToby Isaac /*@ 10312a4e35b19SJacob Faibussowitsch DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. 10313a68b90caSToby Isaac 1031420f4b53cSBarry Smith Collective 10315a68b90caSToby Isaac 10316a68b90caSToby Isaac Input Parameters: 10317a1cb98faSBarry Smith + dm - The `DMPLEX` object 10318a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. 10319a1cb98faSBarry Smith Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10320a1cb98faSBarry Smith - anchorIS - The list of all anchor points. Must have a local communicator (`PETSC_COMM_SELF` or derivative). 10321a68b90caSToby Isaac 10322a68b90caSToby Isaac Level: intermediate 10323a68b90caSToby Isaac 10324a1cb98faSBarry Smith Notes: 10325a4e35b19SJacob Faibussowitsch Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to 10326a4e35b19SJacob Faibussowitsch an outside value, the anchor constraints set a point's degrees of freedom to be a linear 10327a4e35b19SJacob Faibussowitsch combination of other points' degrees of freedom. 10328a4e35b19SJacob Faibussowitsch 10329a1cb98faSBarry Smith After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling 10330a1cb98faSBarry Smith `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix. 10331a1cb98faSBarry Smith 1033220f4b53cSBarry Smith The reference counts of `anchorSection` and `anchorIS` are incremented. 10333a1cb98faSBarry Smith 103341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()` 10335a68b90caSToby Isaac @*/ 10336d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 10337d71ae5a4SJacob Faibussowitsch { 10338a68b90caSToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10339e228b242SToby Isaac PetscMPIInt result; 10340a68b90caSToby Isaac 10341a68b90caSToby Isaac PetscFunctionBegin; 10342a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10343e228b242SToby Isaac if (anchorSection) { 10344e228b242SToby Isaac PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2); 103459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result)); 103461dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator"); 10347e228b242SToby Isaac } 10348e228b242SToby Isaac if (anchorIS) { 10349e228b242SToby Isaac PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3); 103509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result)); 103511dca8a05SBarry Smith PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator"); 10352e228b242SToby Isaac } 10353a68b90caSToby Isaac 103549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorSection)); 103559566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&plex->anchorSection)); 10356a68b90caSToby Isaac plex->anchorSection = anchorSection; 10357a68b90caSToby Isaac 103589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)anchorIS)); 103599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&plex->anchorIS)); 10360a68b90caSToby Isaac plex->anchorIS = anchorIS; 10361a68b90caSToby Isaac 10362cf9c20a2SJed Brown if (PetscUnlikelyDebug(anchorIS && anchorSection)) { 10363a68b90caSToby Isaac PetscInt size, a, pStart, pEnd; 10364a68b90caSToby Isaac const PetscInt *anchors; 10365a68b90caSToby Isaac 103669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 103679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(anchorIS, &size)); 103689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(anchorIS, &anchors)); 10369a68b90caSToby Isaac for (a = 0; a < size; a++) { 10370a68b90caSToby Isaac PetscInt p; 10371a68b90caSToby Isaac 10372a68b90caSToby Isaac p = anchors[a]; 10373a68b90caSToby Isaac if (p >= pStart && p < pEnd) { 10374a68b90caSToby Isaac PetscInt dof; 10375a68b90caSToby Isaac 103769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10377a68b90caSToby Isaac if (dof) { 103789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 1037963a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p); 10380a68b90caSToby Isaac } 10381a68b90caSToby Isaac } 10382a68b90caSToby Isaac } 103839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(anchorIS, &anchors)); 10384a68b90caSToby Isaac } 10385f7c74593SToby Isaac /* reset the generic constraints */ 103869566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL)); 103873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10388a68b90caSToby Isaac } 10389a68b90caSToby Isaac 10390d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 10391d71ae5a4SJacob Faibussowitsch { 10392f7c74593SToby Isaac PetscSection anchorSection; 103936995de1eSToby Isaac PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 10394a68b90caSToby Isaac 10395a68b90caSToby Isaac PetscFunctionBegin; 10396a68b90caSToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103979566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 103989566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec)); 103999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 104006995de1eSToby Isaac if (numFields) { 10401719ab38cSToby Isaac PetscInt f; 104029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(*cSec, numFields)); 10403719ab38cSToby Isaac 10404719ab38cSToby Isaac for (f = 0; f < numFields; f++) { 10405719ab38cSToby Isaac PetscInt numComp; 10406719ab38cSToby Isaac 104079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(section, f, &numComp)); 104089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp)); 10409719ab38cSToby Isaac } 104106995de1eSToby Isaac } 104119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd)); 104129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 104136995de1eSToby Isaac pStart = PetscMax(pStart, sStart); 104146995de1eSToby Isaac pEnd = PetscMin(pEnd, sEnd); 104156995de1eSToby Isaac pEnd = PetscMax(pStart, pEnd); 104169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd)); 10417a68b90caSToby Isaac for (p = pStart; p < pEnd; p++) { 104189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(anchorSection, p, &dof)); 10419a68b90caSToby Isaac if (dof) { 104209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, p, &dof)); 104219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(*cSec, p, dof)); 10422a68b90caSToby Isaac for (f = 0; f < numFields; f++) { 104239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &dof)); 104249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof)); 10425a68b90caSToby Isaac } 10426a68b90caSToby Isaac } 10427a68b90caSToby Isaac } 104289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(*cSec)); 104299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section")); 104303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10431a68b90caSToby Isaac } 10432a68b90caSToby Isaac 10433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 10434d71ae5a4SJacob Faibussowitsch { 10435f7c74593SToby Isaac PetscSection aSec; 10436ae65431dSMatthew G. Knepley PetscInt pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 104370ac89760SToby Isaac const PetscInt *anchors; 104380ac89760SToby Isaac PetscInt numFields, f; 1043966ad2231SToby Isaac IS aIS; 10440e19f7ee6SMark Adams MatType mtype; 10441e19f7ee6SMark Adams PetscBool iscuda, iskokkos; 104420ac89760SToby Isaac 104430ac89760SToby Isaac PetscFunctionBegin; 104440ac89760SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 104459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cSec, &m)); 104469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &n)); 104479566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, cMat)); 104489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*cMat, m, n, m, n)); 104499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda)); 104509566063dSJacob Faibussowitsch if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda)); 104519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos)); 104529566063dSJacob Faibussowitsch if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos)); 10453e19f7ee6SMark Adams if (iscuda) mtype = MATSEQAIJCUSPARSE; 10454e19f7ee6SMark Adams else if (iskokkos) mtype = MATSEQAIJKOKKOS; 10455e19f7ee6SMark Adams else mtype = MATSEQAIJ; 104569566063dSJacob Faibussowitsch PetscCall(MatSetType(*cMat, mtype)); 104579566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS)); 104589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(aIS, &anchors)); 104596995de1eSToby Isaac /* cSec will be a subset of aSec and section */ 104609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd)); 104619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(section, &sStart, &sEnd)); 104629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &i)); 104630ac89760SToby Isaac i[0] = 0; 104649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &numFields)); 104650ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 10466f19733c5SToby Isaac PetscInt rDof, rOff, r; 10467f19733c5SToby Isaac 104689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 10469f19733c5SToby Isaac if (!rDof) continue; 104709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 104710ac89760SToby Isaac if (numFields) { 104720ac89760SToby Isaac for (f = 0; f < numFields; f++) { 104730ac89760SToby Isaac annz = 0; 10474f19733c5SToby Isaac for (r = 0; r < rDof; r++) { 10475f19733c5SToby Isaac a = anchors[rOff + r]; 10476ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 104779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 104780ac89760SToby Isaac annz += aDof; 104790ac89760SToby Isaac } 104809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 104819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off)); 10482ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 104830ac89760SToby Isaac } 104842f7452b8SBarry Smith } else { 104850ac89760SToby Isaac annz = 0; 104869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 104870ac89760SToby Isaac for (q = 0; q < dof; q++) { 10488ae65431dSMatthew G. Knepley a = anchors[rOff + q]; 10489ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 104909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 104910ac89760SToby Isaac annz += aDof; 104920ac89760SToby Isaac } 104939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 104949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cSec, p, &off)); 10495ad540459SPierre Jolivet for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz; 104960ac89760SToby Isaac } 104970ac89760SToby Isaac } 104980ac89760SToby Isaac nnz = i[m]; 104999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &j)); 105000ac89760SToby Isaac offset = 0; 105010ac89760SToby Isaac for (p = pStart; p < pEnd; p++) { 105020ac89760SToby Isaac if (numFields) { 105030ac89760SToby Isaac for (f = 0; f < numFields; f++) { 105049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof)); 105050ac89760SToby Isaac for (q = 0; q < dof; q++) { 105060ac89760SToby Isaac PetscInt rDof, rOff, r; 105079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 105089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 105090ac89760SToby Isaac for (r = 0; r < rDof; r++) { 105100ac89760SToby Isaac PetscInt s; 105110ac89760SToby Isaac 105120ac89760SToby Isaac a = anchors[rOff + r]; 10513ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 105149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof)); 105159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff)); 10516ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 105170ac89760SToby Isaac } 105180ac89760SToby Isaac } 105190ac89760SToby Isaac } 105202f7452b8SBarry Smith } else { 105219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cSec, p, &dof)); 105220ac89760SToby Isaac for (q = 0; q < dof; q++) { 105230ac89760SToby Isaac PetscInt rDof, rOff, r; 105249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(aSec, p, &rDof)); 105259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(aSec, p, &rOff)); 105260ac89760SToby Isaac for (r = 0; r < rDof; r++) { 105270ac89760SToby Isaac PetscInt s; 105280ac89760SToby Isaac 105290ac89760SToby Isaac a = anchors[rOff + r]; 10530ae65431dSMatthew G. Knepley if (a < sStart || a >= sEnd) continue; 105319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(section, a, &aDof)); 105329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, a, &aOff)); 10533ad540459SPierre Jolivet for (s = 0; s < aDof; s++) j[offset++] = aOff + s; 105340ac89760SToby Isaac } 105350ac89760SToby Isaac } 105360ac89760SToby Isaac } 105370ac89760SToby Isaac } 105389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL)); 105399566063dSJacob Faibussowitsch PetscCall(PetscFree(i)); 105409566063dSJacob Faibussowitsch PetscCall(PetscFree(j)); 105419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(aIS, &anchors)); 105423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105430ac89760SToby Isaac } 105440ac89760SToby Isaac 10545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 10546d71ae5a4SJacob Faibussowitsch { 10547f7c74593SToby Isaac DM_Plex *plex = (DM_Plex *)dm->data; 10548f7c74593SToby Isaac PetscSection anchorSection, section, cSec; 1054966ad2231SToby Isaac Mat cMat; 1055066ad2231SToby Isaac 1055166ad2231SToby Isaac PetscFunctionBegin; 1055266ad2231SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 105539566063dSJacob Faibussowitsch PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL)); 1055466ad2231SToby Isaac if (anchorSection) { 1055544a7f3ddSMatthew G. Knepley PetscInt Nf; 10556e228b242SToby Isaac 105579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 105589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec)); 105599566063dSJacob Faibussowitsch PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat)); 105609566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 105619566063dSJacob Faibussowitsch if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat)); 105629566063dSJacob Faibussowitsch PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL)); 105639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&cSec)); 105649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&cMat)); 1056566ad2231SToby Isaac } 105663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1056766ad2231SToby Isaac } 10568a93c429eSMatthew G. Knepley 10569d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) 10570d71ae5a4SJacob Faibussowitsch { 10571a93c429eSMatthew G. Knepley IS subis; 10572a93c429eSMatthew G. Knepley PetscSection section, subsection; 10573a93c429eSMatthew G. Knepley 10574a93c429eSMatthew G. Knepley PetscFunctionBegin; 105759566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 1057628b400f6SJacob Faibussowitsch PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain"); 1057728b400f6SJacob Faibussowitsch PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain"); 10578a93c429eSMatthew G. Knepley /* Create subdomain */ 1057930cbcd5dSksagiyam PetscCall(DMPlexFilter(dm, label, value, PETSC_FALSE, PETSC_FALSE, NULL, subdm)); 10580a93c429eSMatthew G. Knepley /* Create submodel */ 105819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &subis)); 105829566063dSJacob Faibussowitsch PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection)); 105839566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(*subdm, subsection)); 105849566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&subsection)); 105859566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, *subdm)); 10586a93c429eSMatthew G. Knepley /* Create map from submodel to global model */ 10587a93c429eSMatthew G. Knepley if (is) { 10588a93c429eSMatthew G. Knepley PetscSection sectionGlobal, subsectionGlobal; 10589a93c429eSMatthew G. Knepley IS spIS; 10590a93c429eSMatthew G. Knepley const PetscInt *spmap; 10591a93c429eSMatthew G. Knepley PetscInt *subIndices; 10592a93c429eSMatthew G. Knepley PetscInt subSize = 0, subOff = 0, pStart, pEnd, p; 10593a93c429eSMatthew G. Knepley PetscInt Nf, f, bs = -1, bsLocal[2], bsMinMax[2]; 10594a93c429eSMatthew G. Knepley 105959566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(*subdm, &spIS)); 105969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(spIS, &spmap)); 105979566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &Nf)); 105989566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dm, §ionGlobal)); 105999566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal)); 106009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd)); 10601a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10602a93c429eSMatthew G. Knepley PetscInt gdof, pSubSize = 0; 10603a93c429eSMatthew G. Knepley 106049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof)); 10605a93c429eSMatthew G. Knepley if (gdof > 0) { 10606a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10607a93c429eSMatthew G. Knepley PetscInt fdof, fcdof; 10608a93c429eSMatthew G. Knepley 106099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof)); 106109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof)); 10611a93c429eSMatthew G. Knepley pSubSize += fdof - fcdof; 10612a93c429eSMatthew G. Knepley } 10613a93c429eSMatthew G. Knepley subSize += pSubSize; 10614a93c429eSMatthew G. Knepley if (pSubSize) { 10615a93c429eSMatthew G. Knepley if (bs < 0) { 10616a93c429eSMatthew G. Knepley bs = pSubSize; 10617a93c429eSMatthew G. Knepley } else if (bs != pSubSize) { 10618a93c429eSMatthew G. Knepley /* Layout does not admit a pointwise block size */ 10619a93c429eSMatthew G. Knepley bs = 1; 10620a93c429eSMatthew G. Knepley } 10621a93c429eSMatthew G. Knepley } 10622a93c429eSMatthew G. Knepley } 10623a93c429eSMatthew G. Knepley } 10624a93c429eSMatthew G. Knepley /* Must have same blocksize on all procs (some might have no points) */ 106259371c9d4SSatish Balay bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; 106269371c9d4SSatish Balay bsLocal[1] = bs; 106279566063dSJacob Faibussowitsch PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax)); 106289371c9d4SSatish Balay if (bsMinMax[0] != bsMinMax[1]) { 106299371c9d4SSatish Balay bs = 1; 106309371c9d4SSatish Balay } else { 106319371c9d4SSatish Balay bs = bsMinMax[0]; 106329371c9d4SSatish Balay } 106339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(subSize, &subIndices)); 10634a93c429eSMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 10635a93c429eSMatthew G. Knepley PetscInt gdof, goff; 10636a93c429eSMatthew G. Knepley 106379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof)); 10638a93c429eSMatthew G. Knepley if (gdof > 0) { 10639a93c429eSMatthew G. Knepley const PetscInt point = spmap[p]; 10640a93c429eSMatthew G. Knepley 106419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff)); 10642a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10643a93c429eSMatthew G. Knepley PetscInt fdof, fcdof, fc, f2, poff = 0; 10644a93c429eSMatthew G. Knepley 10645a93c429eSMatthew G. Knepley /* Can get rid of this loop by storing field information in the global section */ 10646a93c429eSMatthew G. Knepley for (f2 = 0; f2 < f; ++f2) { 106479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof)); 106489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof)); 10649a93c429eSMatthew G. Knepley poff += fdof - fcdof; 10650a93c429eSMatthew G. Knepley } 106519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof)); 106529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof)); 10653ad540459SPierre Jolivet for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc; 10654a93c429eSMatthew G. Knepley } 10655a93c429eSMatthew G. Knepley } 10656a93c429eSMatthew G. Knepley } 106579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(spIS, &spmap)); 106589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is)); 10659a93c429eSMatthew G. Knepley if (bs > 1) { 10660a93c429eSMatthew G. Knepley /* We need to check that the block size does not come from non-contiguous fields */ 10661a93c429eSMatthew G. Knepley PetscInt i, j, set = 1; 10662a93c429eSMatthew G. Knepley for (i = 0; i < subSize; i += bs) { 10663a93c429eSMatthew G. Knepley for (j = 0; j < bs; ++j) { 106649371c9d4SSatish Balay if (subIndices[i + j] != subIndices[i] + j) { 106659371c9d4SSatish Balay set = 0; 106669371c9d4SSatish Balay break; 106679371c9d4SSatish Balay } 10668a93c429eSMatthew G. Knepley } 10669a93c429eSMatthew G. Knepley } 106709566063dSJacob Faibussowitsch if (set) PetscCall(ISSetBlockSize(*is, bs)); 10671a93c429eSMatthew G. Knepley } 10672a93c429eSMatthew G. Knepley /* Attach nullspace */ 10673a93c429eSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 10674a93c429eSMatthew G. Knepley (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f]; 10675a93c429eSMatthew G. Knepley if ((*subdm)->nullspaceConstructors[f]) break; 10676a93c429eSMatthew G. Knepley } 10677a93c429eSMatthew G. Knepley if (f < Nf) { 10678a93c429eSMatthew G. Knepley MatNullSpace nullSpace; 106799566063dSJacob Faibussowitsch PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace)); 106806823f3c5SBlaise Bourdin 106819566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace)); 106829566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nullSpace)); 10683a93c429eSMatthew G. Knepley } 10684a93c429eSMatthew G. Knepley } 106853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10686a93c429eSMatthew G. Knepley } 10687c0f0dcc3SMatthew G. Knepley 10688c0f0dcc3SMatthew G. Knepley /*@ 10689c0f0dcc3SMatthew G. Knepley DMPlexMonitorThroughput - Report the cell throughput of FE integration 10690c0f0dcc3SMatthew G. Knepley 10691a1cb98faSBarry Smith Input Parameters: 10692a1cb98faSBarry Smith + dm - The `DM` 10693a1cb98faSBarry Smith - dummy - unused argument 10694a1cb98faSBarry Smith 10695a1cb98faSBarry Smith Options Database Key: 10696a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor 10697c0f0dcc3SMatthew G. Knepley 10698c0f0dcc3SMatthew G. Knepley Level: developer 10699c0f0dcc3SMatthew G. Knepley 107001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()` 10701c0f0dcc3SMatthew G. Knepley @*/ 10702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) 10703d71ae5a4SJacob Faibussowitsch { 10704b665b14eSToby Isaac PetscLogHandler default_handler; 10705b665b14eSToby Isaac 107062611ad71SToby Isaac PetscFunctionBegin; 107072611ad71SToby Isaac PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10708b665b14eSToby Isaac PetscCall(PetscLogGetDefaultHandler(&default_handler)); 10709b665b14eSToby Isaac if (default_handler) { 10710c0f0dcc3SMatthew G. Knepley PetscLogEvent event; 10711c0f0dcc3SMatthew G. Knepley PetscEventPerfInfo eventInfo; 10712c0f0dcc3SMatthew G. Knepley PetscReal cellRate, flopRate; 10713c0f0dcc3SMatthew G. Knepley PetscInt cStart, cEnd, Nf, N; 10714c0f0dcc3SMatthew G. Knepley const char *name; 10715c0f0dcc3SMatthew G. Knepley 107169566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 107179566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 107189566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 107199566063dSJacob Faibussowitsch PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event)); 10720b665b14eSToby Isaac PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo)); 10721c0f0dcc3SMatthew G. Knepley N = (cEnd - cStart) * Nf * eventInfo.count; 10722c0f0dcc3SMatthew G. Knepley flopRate = eventInfo.flops / eventInfo.time; 10723c0f0dcc3SMatthew G. Knepley cellRate = N / eventInfo.time; 1072463a3b9bcSJacob 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))); 107252611ad71SToby Isaac } else { 10726b665b14eSToby 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."); 107272611ad71SToby Isaac } 107283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10729c0f0dcc3SMatthew G. Knepley } 10730